iOS 指定初始化器:使用 NS_DESIGNATED_INITIALIZER [英] iOS Designated Initializers : Using NS_DESIGNATED_INITIALIZER

查看:21
本文介绍了iOS 指定初始化器:使用 NS_DESIGNATED_INITIALIZER的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在 XCode 6 中引入了这个新宏:NS_DESIGNATED_INITIALIZER

我在网上搜索过,但实际上找不到任何关于如何使用它的好文档.

在语法上,我们可以像这样使用它:

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

但是用这个宏标记一个初始化器可能有什么好处,以及我们在使用这个宏时应该注意什么?

我主要对这个宏的用例感兴趣.任何链接/文档将不胜感激.

解决方案

NS_DESIGNATED_INITIALIZER 的使用在 http://useyourloaf.com/blog/2014/08/19/xcode-6-objective-c-modernization.html:p><块引用>

指定的初始化器保证对象被完全初始化通过向超类发送初始化消息.这实现细节对类的用户来说变得很重要,当他们将其子类化.指定初始化器的详细规则:

  • 指定的初始化程序必须(通过 super)调用指定的超类的初始化器.其中 NSObject 是 this 的超类只是[超级初始化].
  • 任何便利构造器都必须调用另一个类中的初始化器 - 最终导致指定的初始化器.
  • 具有指定初始化器的类必须实现所有超类的指定初始值设定项.

例如,如果你的界面是

@interface MyClass : NSObject@property(copy, nonatomic) NSString *name;-(instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER;-(实例类型)初始化;@结尾

然后编译器检查(方便)初始化器 init 是否调用(指定的)初始化程序 initWithName:,所以这会导致警告:

-(instancetype)init{self = [超级初始化];回归自我;}

这样就可以了:

-(instancetype)init{self = [self initWithName:@""];回归自我;}

Swift 中,关于指定初始化器和便利初始化器的规则更加严格,如果你混合使用 Objective-C 和 Swift 代码,标记指定的 Objective-C 初始化器有助于编译器执行规则.

例如,这个 Swift 子类会导致编译器错误:

类 SwClass: MyClass {var foo : 字符串初始化(富:字符串){self.foo = foo超级初始化()}}

这样就可以了:

类 SwClass: MyClass {var foo : 字符串初始化(富:字符串){self.foo = foo超级初始化(名称:")}}

We have this 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.

Syntactically, we can use it like :

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

But what are the possible advantages of marking an initializer with this macro, and also what are the things we should be looking at when using this ?

I am mainly interested in the use cases of this macro. Any links / documentation would be appreciated.

解决方案

The use of NS_DESIGNATED_INITIALIZER is nicely explained in http://useyourloaf.com/blog/2014/08/19/xcode-6-objective-c-modernization.html:

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.

As an example, if your interface is

@interface MyClass : NSObject
@property(copy, nonatomic) NSString *name;
-(instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER;
-(instancetype)init;
@end

then the compiler checks if the (convenience) initializer init calls the (designated) initializer initWithName:, so this would cause a warning:

-(instancetype)init
{
    self = [super init];
    return self;
}

and this would be OK:

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

In Swift the rules about designated and convenience initializers are even more strict, and if you mix Objective-C and Swift code, marking the designated Objective-C initializers helps the compiler to enforce the rules.

For example, this Swift subclass would cause an compiler error:

class SwClass: MyClass {
    var foo : String
    init(foo : String) {
        self.foo = foo
        super.init()
    }
}

and this would be OK:

class SwClass: MyClass {
    var foo : String
    init(foo : String) {
        self.foo = foo
        super.init(name: "")
    }
}

这篇关于iOS 指定初始化器:使用 NS_DESIGNATED_INITIALIZER的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆