NSDate 内存管理使用 ARC Over Release
Posted
技术标签:
【中文标题】NSDate 内存管理使用 ARC Over Release【英文标题】:NSDate Memory Management Using ARC Over Release 【发布时间】:2013-09-20 19:34:09 【问题描述】:我正在构建一个应用程序,其中使用标准视图控制器中的 UIDatePicker 设置 NSDate 对象。日期被添加到另一个类的可变字典中。当同一个类尝试访问日期对象时,它已经准备好被释放,导致崩溃。 此外,这只是在使用 Xcode 5 编译后才出现的问题。
示例代码
@interface SomeViewController ()
@property (nonatomic, strong) UIDatePicker *datePicker;
@property (nonatomic, strong) ChangeTracker *changeTracker; // Records local changes made to managed objects to send to server
@end
@implementation SomeViewController
// Relevant implementation
- (void)touchSetPicker:(UIButton *)sender
[self setDate:self.datePicker.date forManagedObject:self.someManagedObject];
- (void)setDate:(NSDate *)date forManagedObject:(NSManagedObject *)managedObject
// Set properties on managed object based on date param
// Pass date to changeTracker class
[self.changeTracker setDate:date forManagedObject:managedObject];
@end
ChangeTracker.m
@interface ChangeTracker ()
@property (nonatomic, strong) NSMutableDictionary *dateChanges;
@end
@implementation ChangeTracker
- (void)setDate:(NSDate *)date forManagedObject:(NSManagedObject *)managedObject
NSString *idProperty = managedObject.idProperty;
self.dateChanges[idProperty] = date;
- (void)compileAllChanges
for (NSString *idProperty in [self.dateChanges allKeys])
// Here is where the crash occurs due to the date being deallocated
NSDate *date = self.dateChanges[idProperty];
@end
启用僵尸对象后,我收到错误消息: -[__NSDate release]: 消息发送到释放的实例
该项目正在使用 ARC,因此我无法明确尝试保留此对象。任何帮助将不胜感激。
【问题讨论】:
什么时候调用compileAllChanges? compileAllChanges 在按钮点击时从 ViewController 调用:[self.changeTracker compileAllChanges]; 【参考方案1】:我遇到了@gabriel-ortega 描述的相同问题 我想知道他是否找到了解决问题的方法。
编辑:为了回答我自己并希望也能帮助其他人,我找到了问题的原因。
正如苹果文档所说:
为了允许与手动保留释放代码的互操作,ARC 对方法命名施加了限制:您不能为访问器指定以 new 开头的名称。这反过来意味着,例如,除非您指定不同的 getter,否则您不能声明名称以 new 开头的属性:
// Won't work: property NSString *newTitle; // Works: property (getter=theNewTitle) NSString *newTitle;
我的属性名称是 newPath
,这说明了...
【讨论】:
哇,惊人的发现!给我带来问题的日期属性是“newDueDate”。【参考方案2】:如果您使用 ARC,则不应出现僵尸。你有一个变量声明为 unsafe_unretained 而不是弱?还是您在某处使用第三方库?内部使用手动引用计数代码的库可能是僵尸的来源。
unsafe_unretained 的不当使用可能会导致您引用已释放的对象,但是对于正常的强引用和弱引用,弱引用一释放就会被清零,因此一旦它们被释放,您应该无法向它们发送消息已被释放。
另一种可能性是滥用桥接演员表。那会搞砸ARC。你在使用桥接演员吗?
【讨论】:
项目中有 unsafe_unretained 属性(很大),但不与相关代码交互。 DataStoreController 不使用 ARC,但这从来都不是问题。 要明确项目使用核心数据和 mogenerator 声明一些 unsafe_unretained NSString 属性。 使用分配工具运行项目时,我发现 managedObject 的一个特定属性导致 ARC 在访问值时过度释放它。仍然不确定该属性是如何配置错误的,因为该类的其他日期属性之间没有区别。以上是关于NSDate 内存管理使用 ARC Over Release的主要内容,如果未能解决你的问题,请参考以下文章