ARC下块中声明的对象的生命周期是多少?

时间:2012-01-15 13:50:43

标签: objective-c ios automatic-ref-counting objective-c-blocks

我对块和ARC的理解存在差距,我希望得到一些帮助。我收到了一个来自动画完成块的测试人员的崩溃报告。崩溃如下:

  

异常类型:EXC_BAD_ACCESS(SIGSEGV)

     

例外代码:KERN_INVALID_ADDRESS位于0xf0000010

这发生在以下动画完成块内(使用animateWithDuration:animations:completion:)。我正在使用临时变量交换两个视图控制器:

{
    [current wasMovedOffScreen];
    PlayerViewController *temp = current;
    current = next;
    next = temp;
}

next = temp;是崩溃发生的行。动画的持续时间为0.3秒。

此代码在视图控制器内执行,该视图控制器充当两个其他视图控制器的容器,用于模拟用户通过对象列表(如导航控制器),但具有许多意味着导航控制器的自定义不适合我。

两个子视图控制器称为“当前”和“下一个” - 您可以猜测当前控制器显示当前内容,下一个用于在用户在列表中移动时在新项目中设置动画。

如果我更改了块以便在实现中声明temp(以及currentnext),则崩溃停止。然而,对于我来说,根据定义本地和临时的东西,我似乎没有必要持有一个类ivar。

所以,

  • 为什么在这个过程中,temp显然是由ARC发布的?
  • 实现这个的正确方法是什么?我应该在块实现中添加一些生命周期限定符吗?
  • 为什么我不能在自己的设备或模拟器中重现崩溃?这两款设备都是运行相同版本iOS(5.0.1)的iPhone 4。

2 个答案:

答案 0 :(得分:1)

在这种情况下,我不认为问题实际上是ARC。默认情况下,变量(包括局部变量)为__strong,因此{1}}应保留在第一个赋值中。

http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/_index.html - 请参阅“变量限定符”

部分

如果你遇到了崩溃,你无法自我复制,总是难以修复。您是否尝试在调试器外部运行应用程序?加载调试器有时可以改变行为。另外,尝试使用NSZombieEnabled或Instruments.app的僵尸工具进行调试。

答案 1 :(得分:0)

如果它确实让你失望,因为你只是在两个视图之间交替,你实际上并不需要所有当前/下一个业务。好吧,如果你想要的话,你可以跟踪当前......但这就是想法。

如果您有房产:

@property (nonatomic, strong) UIViewController *controller1;
@property (nonatomic, strong) UIViewController *controller2;
@property (nonatomic, weak) UIViewController *currentController;

然后你可以有一个方法:

- (id)swapControllers {
    // use the current controller to figure out what the next controller is, so
    // you don't have to do the two way swap. do in the completion, if you like.    
    UIViewController *nextController = ([self.currentController isEqual:self.controller1]) ? self.controller1 : self.controller2;
    [UIView animateWithDuration:.25
                     animations:^{
                         // TODO: some animations on currentController and nextController
                     } completion:^(BOOL finished) {
                         [self.currentController wasMovedOffScreen];
                         self.currentController = nextController;
                     }];
}

关于你的原始问题,ARC知道如何处理块很好 - 如果你没有使用它,我可能会问你是否忘记复制在别处声明的块,然后存储,然后在完成时传入处理程序。既然情况并非如此,并且因为你还没有得到一个复制品...我猜你可能正在运行一个beta版本的sdk - 最近在测试版中出现了一些ARC漏洞。如果是这样,您可以尝试使用上一个稳定版本进行构建,并查看是否获得了更好的结果。