以“new”前缀开头的属性名称导致 iOS 中的 BAD_ACCESS 错误

Posted

技术标签:

【中文标题】以“new”前缀开头的属性名称导致 iOS 中的 BAD_ACCESS 错误【英文标题】:Property name starting with 'new' prefix leads to BAD_ACCESS error in iOS 【发布时间】:2014-06-19 13:45:56 【问题描述】:

我的属性在我的 NSManagedObject 类中声明,名称为“newPrice”,导致“僵尸对象”。经过几个小时的调试,我发现释放此对象但未保留它的方法存在问题。将此属性重命名为“priceNew”后,一切顺利。我不明白为什么这会导致问题。

财产声明:

@property (nonatomic, retain) NSNumber * newPrice;

这个调用导致问题:

[self setPieceStateWithPrice:self.action.newPrice];

在传递了像 self.action.priceNew 这样重命名的参数后,一切顺利......

【问题讨论】:

【参考方案1】:

不要那样做。

在 Objective-C 命名约定中,名称以 new 开头的方法应返回保留对象。使用 ARC,该命名约定成为一项要求。这意味着一个普通的 ARC 编译方法不应该以名称 new 开头,因为编译器会假定它的保留计数已经为 1。

引用文档:

您拥有您创建的任何对象

您使用名称以“alloc”开头的方法创建对象, “new”、“copy”或“mutableCopy”(例如,alloc、newObject 或 可变复制)。

【讨论】:

很好奇这种约定是否仍然是 Swift 中的最佳实践。从功能上讲,在属性名称前加上 new 在 Swift 中似乎是完全安全的(对保留计数没有影响,编译也没有问题)。有什么想法吗? 如果将变量声明为动态变量,则在 Swift 中不安全! “当从这样的函数或方法返回时,ARC 会在返回语句的评估点保留值,然后再离开所有本地范围”。根据Clang 中所说的,该值应在从newPrice 返回之前保留。因此,它保留计数为 1 的断言应该是正确的。这意味着它实际上不应该被过度发布。 如果我要使用变量“newsId”,会导致问题吗?只是想知道【参考方案2】:

属性具有自动为它们合成的方法。因此,拥有一个属性意味着拥有一个同名的方法。

alloccopyinitmutableCopynew 开头的方法对它们如何处理内存有特殊的假设。除非您有非常充分的理由,否则您应该避免使用这些前缀。

来自Clang 3.5 documentation | Objective-C Automatic Reference Counting | Retained return values

返回可保留对象指针类型的函数或方法可以标记为返回保留值,表示调用者期望获得 +1 保留计数的所有权。

alloc、copy、init、mutableCopy 和 new 系列中的方法被隐式标记为 attribute((ns_returns_retained))。这可以通过显式标记方法 attribute((ns_returns_not_retained)) 来抑制。

【讨论】:

我不知道那个编译器开关。感谢分享那个金块。 (当你第一次发布它时投了回去。)看起来这个开关在苹果代码中的使用方式是在方法前面加上NS_RETURNS_RETAINED

以上是关于以“new”前缀开头的属性名称导致 iOS 中的 BAD_ACCESS 错误的主要内容,如果未能解决你的问题,请参考以下文章

WCF 反序列化中的 XmlException:“名称不能以 '<' 开头”-在自动属性支持字段中

Xcode 6 中的 iCloud 容器名称前缀更改

具有以字符串开头的属性的元素的 jQuery 选择器

无法定义以 keycloak 开头的属性

在 Apache RewriteRule 指令中设置环境变量时,是啥导致变量名称以“REDIRECT_”为前缀?

如何在 TypeScript 类中正确声明计算属性名称?