Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何使用NS_指定的_初始值设定项并重写init?_Ios_Objective C_Xcode_Macos - Fatal编程技术网

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
现在我可以安全地
返回nilinit
方法中使用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“只是”私有化。我现在就去投票。