1

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?

8
  • Why you want to loose the Dynamism of Objective-C if you are not sure the array will hold what kind of objects? Commented Jan 8, 2016 at 12:23
  • 1
    This answer can maybe help you : stackoverflow.com/a/5198040/3222713 Commented Jan 8, 2016 at 12:26
  • Thanks @Pipiks, I understand it as to use the lightweight typing. Commented Jan 8, 2016 at 12:32
  • @AnoopVaidya Not knowing the type of thing an array will hold is not the general case and likely poor design. Commented Jan 8, 2016 at 12:40
  • 1
    for <NSString *>, the items should be @"...", for <NSNumber *> the items should be @(...), that is why you get the warning, you add NSNumber in spite of you defined the array's item type is NSString. Commented Jan 8, 2016 at 17:00

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

Comments

4

Yes, one should use generics to provide further type specification information both to the compiler and for the developers.

Providing the type of object that an array will contain in the declaration is at a minimum a documentation gain and error checking is an additional benefit.

There is also the hope that type checking will improve in future versions of the compiler.

But in general mixing types in an array by accident has not been a problem, such mistakes tend to show confusion on the part of the developer. If I have an array of Motorcycle objects and add a Juggler object I either have a major design mismatch error or major confusion.

The best defense is good class and variable naming, not array but motorcycleList and jugglerList. Then if I have motorcycleList addObject:juggler it is quickly apparent there is an error right when the statement is being written.

This addition to the ObjC language is just a step in a progression of explicit specification:

id x = [NSMutableArray new];
NSMutableArray *list = [NSMutableArray new];
NSArray<NSString *> *stringList = [NSMutableArray new];

8 Comments

The documentation bit is so important that even if there was no checking, it still would be worth to use generics.
One implementation comes to my mind, assume I have an NSView and I loop through all the subViews, it may contain NSButton, NSTextField, NSBox, NSView etc. So in future how will be do this? Is this really a design flaw?
That is a poor example because they are all subclasses of NSView, it is an array of NSView objects. Throwing in an NSNumber would be inappropriate.
Reductio ad absurdum?
I've seen a lot of mistakes from people putting the wrong things in arrays. The most common in my experience is when there are models and view models (which is particularly bad because they often have many of the same methods so can often "work"). A particularly notorious example for one team was a system with both Person and PersonRecord classes. Someone would make arrays of PersonRecords and call the variable people and later maintainers would make exactly the mistake you'd imagine. Careful naming is so important, but generics would have saved us a lot of headaches.
|
0

Because it does trigger the warning described in the question, using the constructor with specified generic type ([NSMutableArray<NSString *> ...];) is a better approach.

But we can assume that generics in Objective-C were introduced for transitioning to Swift, and in that regard, using Swift directly is even better.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.