fzw*_*zwo 11 objective-c automatic-ref-counting
注意:这是由于一些XCode beta版本中的错误已经修复.如果您遇到ARC问题,此问题和答案可能无法帮助您.
我正在将我的项目从手动引用计数迁移到ARC,并且偶然发现了一个问题:如何确保保留属性的自定义setter实际保留?
在myClass.h,我宣布了一个财产:@property (retain) NSDate *date.无论我是手动设置__strongivar还是自动生成它都无关紧要.
在实现中,我当然要@synthesize date实现一个自定义setter(或者只是下载demo Xcode项目):
- (void)setDate:(NSDate *)newDate
{
if (allowedToSetNewDate)
{
date = newDate;
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎没有保留日期,并且message sent to deallocated instance当newName(自动)发布它来自哪里时,尝试myClass.date稍后访问时提供给我(提供Zombie已启用;否则,它只是静默崩溃).
更改使用的setter date = [newDate copy]可以解决错误,但实际上并不是我想要的.删除自定义setter也有效,但显然不是必需的.
我在这里错过了什么?如何确保保留属性的自定义setter实际保留在ARC环境中?这似乎是一项基本而且常见的任务,我认为我忽略了一些非常明显的事情.
(注意:这不属于任何Apple NDA的条款,因为ARC作为LLVM的一部分公开发布)
编辑:我已经创建了一个小型Xcode项目来演示该问题并将其上传到github.随意下载并玩游戏.我的机智已经结束了(尽管我的机智今天并不是最好的,不可否认).
编辑:对于此示例项目,此问题已解决(请参阅已接受的答案).不幸的是,在我无法分享的更大的项目中,问题仍然存在.作为一种解决方法,我添加了strong复合setter的重复属性(ivars不起作用).新的自定义setter现在看起来像这样:
- (void)setDate:(NSDate *)newDate
{
if (allowedToSetNewDate)
{
self.date_arcretain = newDate; //this property is only there as a workaround. ARC properly retains it, but only if the setter is synthesized
date = newDate;
}
}
Run Code Online (Sandbox Code Playgroud)
BJ *_*mer 12
这看起来像是我的错误; 你的代码应该没问题.如果您还没有这样做,请在http:// bugreport.apple.com上提交一个错误,并附上您的示例项目.
编辑:在进一步检查您的示例项目时,这不是错误.
在您的样本项目的overreleased对象是没有的NSDate实例.您可以完全注释掉tc.date = now示例项目中的调用,但仍然会看到相同的崩溃.事实上,你可以完全取出NSDate的东西.过度释放的对象实际上是TestVC对象本身.
这是正在发生的事情.
在iOS 4.0中,UIWindow获得了一个rootViewController属性.以前您只需要[self.window addSubview:myRootcontroller.view]启动应用程序,现在这个更改意味着窗口实际上会引用根视图控制器.这对于传递旋转通知等非常重要.过去,我相信UIWindow会在添加第一个子视图时自动尝试设置rootViewController(如果尚未设置),但是在您的示例项目中显然没有发生.这可能是由于您创建视图的方式,或者可能是由于iOS 5.0中的更改.无论哪种方式,都没有记录行为,所以你不能依赖它发生.
在大多数情况下,您的app委托将有一个指向根视图控制器的ivar.这不是严格要求的,但通常会发生什么.但是,在您提供的示例项目中,视图控制器不属于应用程序委托.你也没把它设置为窗口的根视图控制器.结果,在该-application:didFinishLaunchingWithOptions:方法结束时,没有任何东西留下对视图控制器的强引用.您的应用代表没有抓住它,窗口本身并没有坚持下去.因此,ARC将其视为局部变量(它是),并在方法结束时释放它.
当然,这并不会改变你UIButton仍然有一个针对你的控制器的动作方法的事实.但正如文档中所述,-addTarget:action:forControlEvents:不保留目标.所以它UIButton有一个悬挂式引用你的视图控制器,现在已被解除分配,因为没有人强烈引用它.因此崩溃.
解决此问题的方法是在应用委托中更改此行:
[self.window addSubview:tc.view];
Run Code Online (Sandbox Code Playgroud)
对此:
self.window.rootViewController = tc;
Run Code Online (Sandbox Code Playgroud)
通过这一次改变,现在一切正常.
编辑:还要确保未启用"预先检查ARC迁移代码"设置,因为这会导致编译器将代码视为手动管理,这不会插入正确的保留/释放调用.
| 归档时间: |
|
| 查看次数: |
3961 次 |
| 最近记录: |