Ios 如何使用NS_指定的_初始值设定项并重写init?
好吧,这是一个公认的最佳实践问题,但我想把它做好,希望有人能启发我: 该场景相当标准,但有一个转折点: 在我编写的框架中有一个类,它直接继承自Ios 如何使用NS_指定的_初始值设定项并重写init?,ios,objective-c,xcode,macos,Ios,Objective C,Xcode,Macos,好吧,这是一个公认的最佳实践问题,但我想把它做好,希望有人能启发我: 该场景相当标准,但有一个转折点: 在我编写的框架中有一个类,它直接继承自NSObject。它有一个指定的初始值设定项,其中包含许多参数,其中大多数参数是非null。因为这是一个框架的一部分,所以我显式地使用了NS\u指定的\u初始值设定项宏(我在较小的个人应用程序中并不总是这样做)。 问题是,这会导致XCode警告我也重写init,即超类的指定初始值设定项。但除此之外,它还要求我从中调用我的指定的initializer,这是我
NSObject
。它有一个指定的初始值设定项,其中包含许多参数,其中大多数参数是非null
。因为这是一个框架的一部分,所以我显式地使用了NS\u指定的\u初始值设定项
宏(我在较小的个人应用程序中并不总是这样做)。
问题是,这会导致XCode警告我也重写init
,即超类的指定初始值设定项。但除此之外,它还要求我从中调用我的指定的initializer,这是我做不到的,因为我只是缺少对其参数有意义的默认值。
我真的不想在“small”init
中抛出异常,我更希望返回nil
为了消除警告,我在类的扩展中添加了init
作为第二个指定的initializer,如下所示:
@interface MyClassName ()
// some other stuff not relevant`
-(nullable instancetype)init NS_DESIGNATED_INITIALIZER;
@end
现在我可以安全地返回nil在重写的init
方法中使用code>,就像我想要的那样。
这意味着我的文档(我使用的是appledoc)和扩展XCode的代码完成不会告诉使用我的框架的人init
实际上也是一个指定的初始值设定项(因此他们不会意外地使用它),但它仍然存在(例如,在单元测试中,这可能很方便)
我的问题是:除了有人在生产中实际使用它,然后在没有意识到的情况下愉快地向nil发送消息之外,还有什么危险吗?这是在init中抛出异常更可取的少数情况之一吗?而不仅仅是从init
返回nil
(可能还会添加一条注释说不应该调用它)——您应该将它标记为不可用
这不仅会消除关于您没有覆盖NSObject
的指定初始化器的警告,而且如果有人试图调用init
而不是您指定的初始化器,还会生成编译时错误
为此,您可以使用NS\u UNAVAILABLE
宏,或使用UNAVAILABLE\uuuu属性,如所示。使用\uuuu属性的优点是,您可以指定编译器将向用户显示的消息
例如:
@interface Foo : NSObject
-(instancetype) init __attribute__((unavailable("You cannot create a foo instance through init - please use initWithBar:")));
-(instancetype) initWithBar:(Bar*)bar NS_DESIGNATED_INITIALIZER;
@end
...
Foo* fooA = [[Foo alloc] init]; // ERROR: 'init' is unavailable: You cannot create a foo instance through init - please use initWithBar:
Foo* fooB = [[Foo alloc] initWithBar:[[Bar alloc] init]]; // No error
非常感谢,这绝对是首选的方式。在我的例子中,由于一些我没有定义的测试,我可能不得不返回nil
,但我肯定会尝试使用\uuuu属性。这显然是总的解决办法。实际上我忽略了你链接的问题7答案,因为我特别不想将init“只是”私有化。我现在就去投票。