Want to know what's coming next in Objective-C? Keep your ear to the ground.
Objective-C is a rapidly evolving language, in a way that you just don't see in established programming languages. ARC, object literals, subscripting, blocks: in the span of just three years, so much of how we program in Objective-C has been changed (for the better).
All of this innovation is a result of Apple's philosophy of vertical integration. Just as Apple's investment in designing its own chipsets gave them leverage to compete aggressively with their mobile hardware, so too has their investment in LLVM allowed their software to keep pace.
Clang developments range from the mundane to paradigm-changing, but telling the difference takes practice. Because we're talking about low-level language features, it's difficult to understand what implications they may have higher up with API design.
One such example is
subject of this week's article.
In Objective-C, conventions aren't just a matter of coding best-practices, they are implicit instructions to the compiler.
both have return types of
id, yet in
Xcode, the compiler makes all of the correct type
checks. How is this possible?
In Cocoa, there is a convention that methods with
always return objects that are an instance of the
receiver class. These methods are said to have a
related result type.
Class constructor methods, although they similarly
id, don't get the same
type-checking benefit, because they don't follow that
You can try this out for yourself:
[[[NSArray alloc] init] mediaPlaybackAllowsAirPlay]; // ❗ "No visible @interface for `NSArray` declares the selector `mediaPlaybackAllowsAirPlay`" [[NSArray array] mediaPlaybackAllowsAirPlay]; // (No error)
follow the naming convention for being a related
result type, the correct type check against
NSArray is performed. However, the
equivalent class constructor
not follow that convention, and is interpreted as
id is useful for opting-out of type
safety, but losing it when you do want it
The alternative, of explicitly declaring the return
(NSArray *) in the previous
example) is a slight improvement, but is annoying to
write, and doesn't play nicely with subclasses.
This is where the compiler steps in to resolve this timeless edge case to the Objective-C type system:
instancetype is a contextual keyword
that can be used as a result type to signal that a
method returns a related result type. For example:
@interface Person + (instancetype)personWithName:(NSString *)name; @end
id, can only be used as the result type in a method declaration.
instancetype, the compiler will
correctly infer that the result of
+personWithName: is an instance of a
Look for class constructors in Foundation to start
instancetype in the near future.
New APIs, such as
UICollectionViewLayoutAttributes are using
Language features are particularly interesting because, again, it's often unclear of what impact they'll have on higher-level aspects of software design.
instancetype may seem to be a
rather mundane, albeit welcome addition to the
compiler, it can be used to some rather clever ends.
NSURL <MapCollection> *sites = (id)[NSURL mapCollection]; [sites put:[NSURL URLWithString:@"http://www.jonmsterling.com/"] at:@"jon"]; [sites put:[NSURL URLWithString:@"http://www.nshipster.com/"] at:@"nshipster"]; NSURL *jonsSite = [sites at:@"jon"]; // => http://www.jonmsterling.com/
Statically-typed collections would make APIs more expressive--no longer would a developer be unsure about what kinds of objects are allowed in a collection parameter.
Whether or not this becomes an accepted convention in
Objective-C, it's fascinating to how a low-level
instancetype can be used to
change shape of the language (in this case, making it
look more like
instancetype is just one of the many
language extensions to Objective-C, with more being
added with each new release.
Know it, love it.
And take it as an example of how paying attention to the low-level details can give you insights into powerful new ways to transform Objective-C.