Usage of iOS Designated Initializers (NS_DESIGNATED_INITIALIZER)

New macro being introduced in XCode 6 : NS_DESIGNATED_INITIALIZER

I searched on the net, but couldn't really find any good documentation as to how to use this.

we can use it like :

- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

Finally got the good document about the usage of  Designated Initialize:

The Infer designated initializer methods conversion identifies and tags the designated initializers of a class with NS_DESIGNATED_INITIALIZER. To understand why that is useful it is worth recapping how object initialization works in Objective-C. Creation of an Objective-C object is a two step process of allocation and then initialization usually written as a single line of code:

MyObject *object = [[MyObject alloc] init];

The initialization method takes care of setting values for any instance variables as well as any other setup tasks for the object. A class can have many initializer methods, by convention named with the prefix init. For example, a class with an instance variable name that must always be set may have an initializer that includes the name:

- (instancetype)init {
  return [self initWithName:@"Unknown"];
}

- (instancetype)initWithName:(NSString *)name {
  self = [super init];
  if (self) {
    _name = [name copy];
  }
  return self;
}

The plain init method is in this case a convenience initializer which simply calls the designated initializer initWithName: with a default value. The designated initializer guarantees the object is fully initialised by sending an initialization message to the superclass. The implementation detail becomes important to a user of the class when they subclass it. The rules for designated initializers in detail:

  • A designated initializer must call (via super) a designated initializer of the superclass. Where NSObject is the superclass this is just [super init].
  • Any convenience initializer must call another initializer in the class - which eventually leads to a designated initializer.
  • A class with designated initializers must implement all of the designated initializers of the superclass.

For a long time there was no way to tell the compiler or user of a class which are the designated initializers (other than in a comment). To correct that situation Clang now has the attribute objc_designated_initializer. In iOS 8 the NS_DESIGNATED_INITIALIZER macro, defined in NSObjCRuntime.h, makes it easy to apply this to a method:

#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))

So for the earlier example we would have:

- (instancetype)init;
- (instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER;

If a convenience initializer you add does not call a designated initializer you will now get a warning. I have seen people reporting problems with some UIKit classes where Apple has not yet tagged designated initializers so as always you will want to test and file bug reports for unexpected results.

Reference links:

http://useyourloaf.com/blog/xcode-6-objective-c-modernization/

https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.html