Ответ 1
Использование NS_DESIGNATED_INITIALIZER
хорошо объяснено в http://useyourloaf.com/blog/2014/08/19/xcode-6-objective-c-modernization.html:
Назначенный инициализатор гарантирует, что объект полностью инициализирован путем отправки сообщения инициализации в суперкласс. детали реализации становятся важными для пользователя класса, когда они подклассифицируют его. Правила для назначенных инициализаторов подробно:
- Назначенный инициализатор должен вызывать (через супер) назначенный инициализатор суперкласса. Где NSObject является суперклассом это просто [super init].
- Любой инициализатор удобства должен вызвать другой инициализатор в классе, что в конечном итоге приводит к назначению инициализатор.
- Класс с назначенными инициализаторами должен реализовать все назначенных инициализаторов суперкласса.
В качестве примера, если ваш интерфейс
@interface MyClass : NSObject
@property(copy, nonatomic) NSString *name;
-(instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER;
-(instancetype)init;
@end
тогда компилятор проверяет, вызван ли (удобство) инициализатор init
(назначенный) инициализатор initWithName:
, поэтому это вызовет предупреждение:
-(instancetype)init
{
self = [super init];
return self;
}
и это будет нормально:
-(instancetype)init
{
self = [self initWithName:@""];
return self;
}
В Swift правила о назначенных и удобных инициализаторах еще более строги, и если вы смешиваете код Objective-C и Swift, то обозначение назначенных инициализаторов Objective-C помогает компилятору обеспечить соблюдение правил.
Например, этот подкласс Swift вызовет ошибку компилятора:
class SwClass: MyClass {
var foo : String
init(foo : String) {
self.foo = foo
super.init()
}
}
и это будет нормально:
class SwClass: MyClass {
var foo : String
init(foo : String) {
self.foo = foo
super.init(name: "")
}
}