ios - 如何使用 NS_DESIGNATED_INITIALIZER 并覆盖 init?

标签 ios objective-c xcode macos

好吧,这确实是一个最佳实践问题,但我想把它做对,所以希望有人能启发我:

场景非常标准,但有一个转折点: 我编写的框架中有一个类直接继承自 NSObject。它有一个带有相当多参数的指定初始化器,其中大部分是 nonnull。由于它是框架的一部分,我明确地使用了 NS_DESIGNATED_INITIALIZER 宏(我并不总是在较小的个人应用程序中这样做)。 问题是这导致 XCode 警告我也覆盖 init,即父类(super class)​​的指定初始化程序。但另外它要求我从它调用我的 指定的初始化器,我不能这样做,因为我只是缺少有意义的参数默认值。 我真的不想在“小”init 中抛出异常,我更愿意返回 nil

为了消除警告,我在类的扩展中添加了 init 作为第二个指定的初始化程序,如下所示:

@interface MyClassName ()
// some other stuff not relevant`

-(nullable instancetype)init NS_DESIGNATED_INITIALIZER;

@end

现在我可以像我想要的那样在覆盖的 init 方法中安全地 return nil; 。 这意味着我的文档(我正在使用 appledoc)和扩展 XCode 的代码完成不会告诉使用我的框架的人 init 实际上也是一个指定的初始化程序(所以他们不会意外使用它) , 但它仍然存在(例如,在单元测试中,这可能会派上用场)。

我的问题是:除了有人实际在生产中使用它之外,这是否有任何危险,然后在没有意识到的情况下愉快地向 nil 发送消息?这会是在 init 中抛出异常更好的少数情况之一吗?

最佳答案

而不是仅仅从 init 返回 nil(并且可能添加一条评论说你不应该调用它)——你应该将它标记为不可用。

这不仅会消除关于你没有覆盖 NSObject 的指定初始化器的警告——如果有人试图调用 init,它还会产生一个编译时错误您指定的初始化程序。

为此,您可以使用NS_UNAVAILABLE 宏,或使用不可用的__attribute__,如this answer 所示。 .使用 __attribute__ 的优点是您可以指定编译器将呈现给用户的消息。

例如:

@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

关于ios - 如何使用 NS_DESIGNATED_INITIALIZER 并覆盖 init?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36574662/

相关文章:

ios - 如何使用两个或多个不同的帐户签署 iOS 项目,只保留一个项目

ios - 使用 NSTimer 调用 performSelectorOnMainThread

ios - 我可以为自己在 Objective-C 中的弃用添加修复吗?

ios - Xcode 单选按钮-按下另一个按钮时更改按钮的背景图像

ios - 如何增加 UItableview 中某个部分的高度

ios - 添加到 UINavigationController 的按钮在导航到下一页后才会显示

ios - xCode 4.3.2 链接错误,但 arch 确实存在。为什么?

ios - 异步调用时 UI 元素在 Segue 后缺少文本

ios - 停止当前的 NSURLConnection

javascript - 空事件监听器 : Is this ok?