Search code examples
objective-cgenericsnsarrayxcode7

Should we write `[NSMutableArray<NSString *> array]`?


Xcode 7 introduced generics. It allows for hint, like:

And allows for warning, like:

But it fails for many things, with no warning at all:

NSMutableArray<NSNumber *> *array;
array = [NSMutableArray<NSNumber *> arrayWithObjects:@0, @"", nil];
NSLog(@"%@", [array[1] class]);// __NSCFConstantString
array = [NSMutableArray<NSNumber *> arrayWithContentsOfURL:[NSURL URLWithString:@"http://ios.eezytutorials.com/sample-files/sample-array-plist.plist"]];
NSLog(@"%@", [array[0] class]); // __NSCFString

So typing the generic creation is kind of unreliable.

Question: should we use the unreliable syntax?

NSMutableArray<NSString *> *array;
array = [NSMutableArray<NSString *> array];
array = [NSMutableArray<NSString *> arrayWithArray:array];
array = [NSMutableArray<NSString *> arrayWithObjects:@"", @"", nil];
array = [NSMutableArray<NSString *> arrayWithContentsOfURL:url];

Or the simplified syntax?

NSMutableArray<NSString *> *array;
array = [NSMutableArray array];
array = [NSMutableArray arrayWithArray:array];
array = [NSMutableArray arrayWithObjects:@"", @"", nil];
array = [NSMutableArray arrayWithContentsOfURL:url];

I'm also concerned by the fact it is obviously not possible to give any compile-time guaranty of the return value of arrayWithContentsOfURL and arrayWithContentsOfFile. So will generics be always useless for those?


Solution

  • You're right, generics in Obj-C are imperfect, but:

    • Some type checking is better than none
    • Makes the code more self-documenting
    • Future versions of Xcode could improve the type inference
    • It already smooths integration with Swift -- something that it only going to get more important over time

    Cons:

    • Doesn't spot 100% of errors -- but does anything?
    • Adds some extra cruft to your code

    In summary: a slight improvement right now but makes your code more future-proof.