我可以在 Objective-C 的 init 中包含 NSError** 作为参数吗?

Posted

技术标签:

【中文标题】我可以在 Objective-C 的 init 中包含 NSError** 作为参数吗?【英文标题】:Can I include NSError** as a parameter in init in Objective-C? 【发布时间】:2015-01-02 12:25:42 【问题描述】:

我的 ios 应用程序从 REST 服务获取 JSON。 JSON 包含状态代码和数据。 如果代码为 200,则数据为请求的对象,否则数据为错误描述。

JSON 可用于构建多种对象,因此我创建了一个工厂类,在其构造函数中获取 json 数据,实例方法根据需要将数据解析为不同的对象。

我的问题是,如果状态码不是 200,是否可以在构造函数中包含 NSError** 作为参数。方法头看起来像这样:

-(instancetype) initWithData:(NSData *) json error: (NSError **) error;

【问题讨论】:

【参考方案1】:

虽然这在语法上完全没问题,但这种方法在功能方面存在问题。

问题在于,当初始化器的调用不成功并返回nil 时,对象的空间仍然被分配(然后立即释放),因为您无法控制它。 allocin的调用

MyObj *obj = [[MyObj alloc] initWithData:data error:&err];

发生在您的代码之外。

最好对调用者隐藏初始化程序,并公开一个类“工厂”方法,如下所示:

+(instancetype) myclassWithData:(NSData *) json error: (NSError **) error;

这样您就可以决定何时调用alloc,这样当您确定没有要创建的对象时,就不会有无用的内存分配/释放。

【讨论】:

我认为他仍然需要这个对象,因为他没有提到返回 nil 但是是的,这是有道理的...... 那是错误的。你会在调用者的某个地方有一个 NSError*,就像使用 NSError** 的任何其他方法一样。这很不寻常,我从未真正看到它完成过,但没有理由不这样做。 @gnasher729 请指出我的答案中我说它不起作用或错误的地方(提示:我没有)。在写负面评论之前阅读答案通常是个好主意。 你说有问题。 1.这个没问题。 2.它不依赖于一个输出参数。我同意“工厂”是更好的方法,但便利分配器并不是更好,因为它可能会返回一个自动释放的对象,该对象的寿命可能会更长。如果你现在想使用“工厂”方法,你应该使用new分配器。 @AminNegm-Awad 我说分配和及时释放空间有问题,以防出现错误,这个问题显然存在。【参考方案2】:

当然,这可能是不寻常的,因为我不记得有任何 iOS API 在 init 中执行此操作,但这并没有错……

【讨论】:

这是一个相当有名的例子:-[NSString initWithContentsOfFile:encoding:error:]【参考方案3】:

没关系。我这样做了很多次。考虑到在 Objective-C 中对象构造不是语言特性,而是框架的一部分。因此初始化器不是特殊的方法。初始化器的唯一特殊情况是它们消耗self 并转移返回值的所有权。但这与out参数无关。

这是不寻常的,因为初始化程序通常不会中断。所以通常你根本不需要它。

【讨论】:

以上是关于我可以在 Objective-C 的 init 中包含 NSError** 作为参数吗?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 Objective-C 中执行 alloc 和 init 在单独的语句中会导致对象根据 Xcode 静态分析器被释放?

Objective-C中如何创建构造函数呢?

Objective-C学习笔记(二十二)——初始化方法init的重写与自己定义

c_cpp 在编译时禁止使用默认的Objective-C -init方法(并提供一个其他超类方法的示例,您可以使用它

Objective-C 中的构造函数

Objective-c:关于self = [super init]的问题