新版本的变更 / Objective-C 2015: Generics and Nullability

// *** before: ***
// a collection held id, so what was inside it could only be guessed from
// the name of the variable
@interface Library : NSObject
@property (nonatomic, copy) NSArray *books;         // of what?
@property (nonatomic, copy) NSDictionary *index;    // key and value of what?
@end

NSArray *books = library.books;
NSString *title = [books objectAtIndex:0];   // no warning at all
NSUInteger length = title.length;            // crashes: it was a Book

// *** in version 2015: ***
// the element type is written in the declaration
@interface Library : NSObject
@property (nonatomic, copy) NSArray<Book *> *books;
@property (nonatomic, copy) NSDictionary<NSString *, Book *> *index;
@property (nonatomic, copy) NSSet<NSString *> *tags;
@end

NSArray<Book *> *books = library.books;
Book *book = books[0];                 // the type is known
NSString *title = book.title;

NSString *wrong = books[0];
// warning: incompatible pointer types initializing NSString * with Book *

Book *found = library.index[@"Moby-Dick"];
for (Book *each in library.books)      // the loop variable is typed too
    NSLog(@"%@", each.title);

// ⚠️ the generics are "lightweight": they exist for the compiler only. The
// runtime has no idea about them, nothing is checked when the array is
// filled from untyped code, and NSArray<Book *> and NSArray are one and
// the same class