我可以在 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
时,对象的空间仍然被分配(然后立即释放),因为您无法控制它。 alloc
in的调用
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学习笔记(二十二)——初始化方法init的重写与自己定义