On Jun 9, 2015, at 11:37 AM, Jens Alfke <jens@mooseyard.com> wrote:The new generics support in Objective-C (starting in Xcode 7) is interesting, although there's no real documentation that I can find, just a one-paragraph mention in the Foundation release notes. But if you look at NSArray.h or NSDictionary.h in the OS X 10.11 or iOS 9 SDK, you can see lots of examples of their use.I'm guessing that the primary reason generics were added was to make the Cocoa APIs more Swift-friendly, so the Swift APIs don't just use [AnyObject] and [AnyObject:AnyValue] everywhere.They'll be useful for Obj-C programming too though, of course. I tried parameterizing the NSArray and NSDictionary types that appear in some APIs in my code, and everything rebuilt without errors. Which is nice in that it didn't break everything and require massive replacing; but on the other hand it shows that generics are pretty loosely type-checked. It seems that you can freely assign between, say, NSArray<NSString*>* and a regular NSArray* without any warnings or errors. In fact you can use the generic form in a method's declaration in a class interface, but leave the old form in the @implementation, without any warnings.
That's right. It may be possible to ratchet up the type checking someday, but at this point trying to type check too strongly is counter-productive in the presence of incomplete adoption.
Note that you should get errors if you convert from one specialized type to another incompatible specialized type: `NSArray<NSView*>` to `NSArray<NSString*>` should fail. The un-specialized forms are the get-out-of-typechecking-free cards.
The advantages of generics in Objective-C include:
* cleaner Swift interoperation
* better self-documentation of code and interfaces
* narrower code completion results
* compile time detection of at least some errors
Be warned that there is no *runtime* checking of the types in Objective-C. If you contrive to store an NSString into your NSArray<NSView*> then you will get the same runtime behavior that you would have seen without the specialized container type. On the plus side that means they add no performance penalty.
(There's also a somewhat related new keyword __kindof, also described in the release notes, that gives you un-typechecked down-casting. So an RHS of type "__kindof NSView*" can be assigned to a LHS of type MyViewClass* without a type-cast. Nice.)
The canonical example is +[NSApplication sharedApplication]. Returning NSApplication means you always have to cast to your real NSApplication subclass, which is little more than syntactic noise. Returning id means you don't need the cast, but it also means you get no type checking and too many code completion results. Returning __kindof NSApplication is a good compromise.
--
Greg Parker gparker@apple.com Runtime Wrangler
No comments:
Post a Comment