A bit hidden but highly convenient when for hybrid projects mixing Swift and Objective-C code.
Misplaced Lens Cap
Xuebing Du
No title available

No title available
taylor price

No title available
todays bird
h
$LAYYYTER
No title available

Product Placement

ellievsbear
2025 on Tumblr: Trends That Defined the Year

pixel skylines

JBB: An Artblog!
NASA

Love Begins

oozey mess
cherry valley forever
we're not kids anymore.
seen from United States
seen from United States
seen from United States
seen from United States

seen from Malaysia
seen from Lithuania
seen from United Arab Emirates
seen from Switzerland

seen from United States

seen from Dominican Republic
seen from United States

seen from Malaysia

seen from United States
seen from United Kingdom

seen from United States

seen from Malaysia
seen from China
seen from United States
seen from Slovakia

seen from Singapore
@cocoadventures
A bit hidden but highly convenient when for hybrid projects mixing Swift and Objective-C code.
Importing Swift Code in Tests
I often see people adding their Swift source files to both their app target and their test target to make them visible in the tests. This is wrong and it can cause subtle issues (unexpected type casting issues) in addition to compiling twice the same files.
The Quick testing framework has a great tutorial on how to properly import your Swift code in your test targets.
This talk will explore the ins and outs of Swift’s take on pointers: typed and raw pointers and buffers, implicit bridging and casting
Excellent talk to clarify pointers in Swift. Must-see for C developers.
The video of my talk at #FrenchKit 2016.
When reaching the point when the app’s performance needs to be improved, it’s easy to do it wrong. By taking a concrete example, we will walk the audience through the process of code optimization: where to focus, what to measure, how to profile, how to tune the code as well as the mistakes to avoid.
The slides are also available.
For its first edition, FrenchKit was amazing. A friendly crowd and great talks.
Last week, Apple launched its latest MacBook Pro laptops. They are deluxe, powerful machines with innovations including the Touch Bar, where the top row of function keys is replaced by a touch-sensitive screen where different functions appear, changing as you change programs. The new models also have a fingerprint sensor built into the power button, to buy stuff online faster than you can say “impulse purchase”.
UIViewController Containment
It's hard to remember how to use the UIViewController containment API, particularly because of its asymmetry.
Adding a child view controller
[self addChildViewController:viewController]; viewController.view.frame = … [self.view addSubview:viewController.view]; [viewController didMoveToParentViewController:self];
Removing a child view controller
[viewController willMoveToParentViewController:nil]; [viewController.view removeFromSuperview]; [viewController removeFromParentViewController];
According to the developer documentation:
If you are implementing your own container view controller, it must call the didMoveToParentViewController: method of the child view controller after the transition to the new controller is complete or, if there is no transition, immediately after calling the addChildViewController: method.
If you are implementing your own container view controller, it must call the willMoveToParentViewController: method of the child view controller before calling the removeFromParentViewController method, passing in a parent value of nil.
Thoughts on iPhone 7 & iOS 10
[iPhone 7] The Home button feels different, indeed, but great. It does feels like a real button with the new haptic engine.
[iOS 10] That Home button does too much though, particularly from the lock screen. Often I will tap it and it won’t unlock iOS, but reveal Apple Pay (double-tap by mistake) or trigger Siri (pressed too strongly). I miss slide-to-unlock.
[iPhone 7] Occasionnally, the GPS went crazy and kept switching locations a couple kilometers away every couple seconds around the city despite having good signal. Sounds like it was picking up different cell towers but returning a “precise” location to Google Maps. Hopefully, that’s not a hardware problem.
[iOS 10] Most apps lose credentials when switching phone. Eg. I have to log back in Dropbox, Twitter, recreate the Google Authenticator entries etc. Why? Would assume everything is in iCloud keychain.
[iOS 10] I had spent some time tagging people in the Photos app on my iPhone 6S (by the way, the face recognition is quite good and identifies people sideways, facing the camera, tiny, with hats, glasses, etc.) My tagged people went missing when I switched to an iPhone 7 (despite restoring an iCloud backup). I know it’s supposed to be local for privacy reasons, but I feel like I lost personal data.
Elasticsearch Inconsistency Issues in Tests
During your tests, you might create an index with a couple documents. You might then notice inconsistencies between different runs of your tests: sometimes a document will be scored higher than another one despite having setup your tests in a seemingly deterministic way.
Indexes in ElasticSearch are divided between shards. Each shard can be located on a different machine in the cluster. This improves the performance and the reliability of the queries.
When you search some text in your documents, ElasticSearch theoretically computes the importance of the search terms in the entire index because the more a term appears in the index, the less relevant it is.
For performance reasons, however, rather than doing so over the entire index, ElasticSearch will compute the scores of each document relative to the shard it's assigned to. It then ranks all the documents throughout the entire cluster and returns the results.
On a large index with lots of documents, if they are assigned truly randomly to shards, this won’t affect the rankings. On the 3 documents in your tests though, this will have an impact if they are assigned to different shards on different runs of your tests.
The solution: enforce that your tests run on a single shard. For instance, when using Elasticsearch-Rails in Ruby:
settings index: { number_of_shards: ENV['RACK_ENV'] == 'test' ? 1 : 5} do mapping do … end end
For a detailed explanation, see Understanding "Query Then Fetch" vs "DFS Query Then Fetch"
disallow-focused-git-hook - Git hook that disallow commits with focused tests.
When working with RSpec, if you grow tired of the "Remove focus" commits, add a pre-commit hook that will watch stray focuses for you.
When it comes to accessibility on mobile devices, some will look at the camera and immediately scratch it off the to-do list. Others will look at the camera and ask what can be done. Someone who can't see may still want to share photos with family, friends, and connections who can. That's why offering a Camera app that's accessible to those with limited or no vision is so important....
Accessibility is very easy on iOS. Turn on Voice Over and make sure all your custom UI elements are accessible before shipping your app.
Understanding bridged casts
With ARC, Objective-C introduced bridged casts, which are C-style casts between toll-free bridged types annotated with either __bridge, __bridge_transfer or __bridge_retained. Using them appropriately is important to avoid memory leaks and crashes, but it can be confusing to know which one to choose.
Though clear, the Apple documentation is abstract:
The compiler does not automatically manage the lifetimes of Core Foundation objects. You tell the compiler about the ownership semantics of objects using either a cast (defined in objc/runtime.h) or a Core Foundation-style macro (defined in NSObject.h):
__bridge transfers a pointer between Objective-C and Core Foundation with no transfer of ownership.
__bridge_transfer or CFBridgingRelease moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC. ARC is responsible for relinquishing ownership of the object.
__bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you. You are responsible for calling CFRelease or a related function to relinquish ownership of the object.
Let’s take a more concrete perspective on this.
Bridge
According to the Apple documentation, there is no transfer of ownership with __bridge. What does this mean?
In the following example, we create an object in the Core Foundation world and access it as a NSString in the NSObject world:
CFStringRef stringRef = CGPDFStringCopyTextString(...); NSString *text = (__bridge NSString *)stringRef; // ... CFRelease(stringRef);
When we instantiate an object with CGPDFStringCopyTextString, its reference count is 1. With __bridge, ARC doesn’t act. Only by making text point to the object, we create a strong reference to this object, increasing its reference count by 1. ARC takes care of decreasing the reference count by 1 when this strong reference isn’t used anymore. There is still the initial reference count from the object’s creation — we need to manually release the object with CFRelease.
Our example, again, with the reference count of our object in the comments:
CFStringRef stringRef = CGPDFStringCopyTextString(...); // 1 (creation) NSString *text = (__bridge NSString *)stringRef; // 2 (text adds a strong reference) // ... NSLog(@"text = %@", text); // 1 (last use of text, ARC release) CFRelease(stringRef); // 0
The more elegant solution here is to use __bridge_transfer.
Bridge Transfer
__bridge_transfer will transfer the ownership of the object to ARC. The compiler takes over the responsibility for releasing the object.
This enables us to rewrite our code:
CFStringRef stringRef = CGPDFStringCopyTextString(...); // 1 (creation) NSString *text = (__bridge_transfer NSString *)stringRef; // 1 (compiler transfers ownership to ARC) // ... NSLog(@"text = %@", text); // 0 (last use of text, ARC release)
It behaves as if we were creating a strong ARC-managed reference to our object while decreasing its reference count with CFRelease:
CFStringRef stringRef = CGPDFStringCopyTextString(...); // 1 (creation) NSString *text = (__bridge NSString *)stringRef; // 2 (text adds a strong reference) CFRelease(stringRef); // 1 // ... NSLog(@"text = %@", text); // 0 (last use of text, ARC release)
Bridge Retained
What happens when we cast a NSObject into a C object?
If we just use a __bridge cast, the compiler doesn’t do anything. ARC releases our object when no more strong references are present:
NSString *text = [[NSString alloc] init]; // 1 CFStringRef stringRef = (__bridge CFStringRef)text; // 1 // ... do something with stringRef NSLog(@"text = %@", text); // 0 (last use of text, ARC release)
The problem is that we don’t control the lifetime of our object. ARC will release it as soon as it sees no more strong references to it. The following code will crash [1]:
NSString *text = [[NSString alloc] init]; // 1 CFStringRef stringRef = (__bridge CFStringRef)text; // 1 // ... NSLog(@"text = %@", text); // 0 (last use of text, ARC release) // do something with stringRef // ** CRASH **
__bridge_retained comes in handy to take ownership of an object during a cast: the reference count of our object is increased. When ARC decreases the reference count because it doesn’t see any later reference, our object stays alive. You now own this object, though; don’t forget to release it:
NSString *text = [[NSString alloc] init]; // 1 CFStringRef stringRef = (__bridge_retained CFStringRef)text; // 2 NSLog(@"text = %@", text); // 1 (last use of text, ARC decrease refs) // We can safely keep using myStringRef. // ... CFRelease(myStringRef); // 0
Conclusion
When using bridged casts, keep in mind who created the object (the initial owner) and who is responsible for releasing it (the current owner, it might not be the initial one if the ownership was already transferred).
If you own a Core Foundation object, use __bridge_transfer to cast it to the NSObject world: ARC is now the owner and you don’t have to deal with releasing it. If you don’t own it, use __bridge — the owner is responsible for releasing it.
If you are bridging in the other direction, ARC generally owns the object. Use __bridge if you know that ARC won’t release the object before you need it. Otherwise, choose __bridge_retained to ensure your object survives even if ARC doesn’t have any strong reference left pointing to it.
Thanks Patrick for reading drafts of this post.
[1] It might not always crash depending on how aggressively the compiler optimizes local variables. In debug mode, for instance, ARC releases objects at the end of the scope and not right after their last use.
Focus on a spec
Specta is a very lightweight spec framework in Objective-C. One nifty feature is the ability to focus on a spec. The focused specs will be the only one to be executed when you launch your tests, making it faster and easier to debug issues.
Just prepend the desired it, describe or context with an f for focus:
describe(@"- performSomeAction", ^{ it(@"does something", ^{ // ... }); fit(@"does something", ^{ // This spec is focused }); });
Just make sure you don't commit your code with the focus still on.
Auto Layout and UIScrollView's contentSize
With Auto Layout enabled, you don't necessarily have to set the content size of your scroll view. It will be determined automatically if the constraints on the subviews tie to the four edges of the scroll view and don't rely on the scroll view to get their size.
Our latest project.
How to add a Shadow on a View in Interface Builder
When you want to add a shadow to a UIView, here is what you usually do:
view.layer.shadowColor = [UIColor blackColor].CGColor; view.layer.shadowOpacity = 0.5; view.layer.shadowRadius = 0.5; view.layer.shadowOffset = CGSizeMake(0, -1); view.layer.masksToBounds = NO;
It’s clunky to write this in code, because that’s just configuring a view, and the remainder of your view configuration is already in IB.
A nice trick in Interface Builder is the use of “User Defined Runtime Parameters” to configure objects without having to write code. With these parameters, you can assign values to keypath of your object provided that they are of one of the supported types: BOOL, number (NSNumber or scalar), NSString, CGPoint, CGSize, CGRect, NSRange, UIColor, UImage name, nil).
Here is what you can do: ⌘⌥ 3 to select the Identity inspector in the Utilities pane.
Now add the following runtime attributes:
You're almost done. Notice how we used shadowUIColor and not shadowColor? That's because - [CALayer setShadowColor:] receives a CGColor and not a UIColor.
The solution? Add a category on CALayer with the following implementation:
@implementation CALayer (Xib) - (void)setShadowUIColor:(UIColor *)shadowUIColor { self.shadowColor = shadowUIColor.CGColor; } @end
You're done!
Hiding the Status Bar on iOS 7
There is no magic involved in showing and hiding the status bar in iOS 7. If you run into issues, it's easy to see a lot of really wrong advice online. On the other hand, while the Apple documentation is well written, you have to know what you are looking for.
To control the status bar for a given view controller, you just need to override the following method:
- (BOOL)prefersStatusBarHidden { return YES; }
There are some special cases:
If your view controller is a child view controller, make sure that the parent delegates this responsibility by implementing childViewControllerForStatusBarHidden.
If you want to hide the status bar when presenting a modal view controller, you need to set modalPresentationStyle to UIModalPresentationFullScreen on the presented view controller. If you need to have modalPresentationStyle set to a different value, then set the flag modalPresentationCapturesStatusBarAppearance to YES.
There is no need to call prefersStatusBarHidden (that's just plain stupid). There is no need to call setNeedsStatusBarAppearanceUpdate unless your implementation of prefersStatusBarHidden is dynamic. Only then you would need to notify the system that the value changed.
- (BOOL)prefersStatusBarHidden { return self.statusBarHidden; } // ... self.statusBarHidden = !self.statusBarHidden; [self setNeedsStatusBarAppearanceUpdate];
Updates - how do you make something great even better, I don't know. But these geniuses obviously know. Can I add one more start? The new interface is more intuitive. Also like the latest addition of tags. Integration with iBooks, WiFi sharing, Facebook sharing. Magnifying glass? Oh my! (They even fixed the silly black screen bug)
An anonymous reviewer of Genius Scan on the AppStore who keeps updating his review with every new update. Thanks!