以“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】:
属性具有自动为它们合成的方法。因此,拥有一个属性意味着拥有一个同名的方法。
以alloc
、copy
、init
、mutableCopy
和new
开头的方法对它们如何处理内存有特殊的假设。除非您有非常充分的理由,否则您应该避免使用这些前缀。
来自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:“名称不能以 '<' 开头”-在自动属性支持字段中