1

我对块和ARC的理解存在差距,我希望得到一些帮助。我收到了一个源自动画完成块的测试器的崩溃报告。碰撞如下:在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在此过程中释放?
  • 执行此操作的正确方法是什么?是否有一些生命周期限定符应添加到块实施中?
  • 为什么我不能在自己的设备或模拟器上重现崩溃?这两款设备都是iPhone 4运行相同版本的iOS(5.0.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知道如何处理块相当不错 - 如果你没有使用它,我可能会问你是否忘记复制其他地方声明的块,然后存储,然后作为完成处理程序传入。由于情况并非如此,并且由于您无法获得repro ...我猜测您可能正在运行beta sdk--最近的beta版本中存在一些ARC漏洞。如果是这样,你可以尝试用最后一个稳定版本来构建,看看你是否能获得更好的结果。

+0

没有贝塔斯参与,缺乏repro真的很烦我! – jrturton 2012-01-15 15:15:44

1

我不认为这个问题实际上是ARC。变量(包括局部变量)默认为__strong,所以current应保留在第一个赋值中。

http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/_index.html - 见“可变量词

如果你有无法重现自己崩溃,它总是会很难修复。你有没有尝试在调试器之外运行应用程序?加载调试器有时可以改变行为。另外,尝试使用NSZombieEnabled或Instruments.app的僵尸工具进行调试。

相关问题