繁体   English   中英

在ARC下的块中声明的对象的生存期是多少?

[英]What is the lifetime of an object declared in a block under ARC?

我对块和ARC的理解存在差距,我希望对此有所帮助。 我已经收到来自测试人员的崩溃报告,该报告源于动画完成块。 崩溃如下:

异常类型:EXC_BAD_ACCESS(SIGSEGV)

异常代码:0xf0000010处的KERN_INVALID_ADDRESS

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

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

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

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

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

如果更改块,以便在实现中声明temp (以及currentnext ),崩溃将停止。 但是,对于我来说,似乎不必为定义为本地和临时的内容保存类ivar。

所以,

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

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

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

如果发生崩溃,您将无法重现自己,这总是很难修复的。 您是否尝试过在调试器之外运行应用程序? 加载调试器有时可能会改变行为。 另外,请尝试使用NSZombieEnabled或Instruments.app的zombie工具进行调试。

如果确实让您满意,那么由于您只是在两个视图之间切换,因此实际上并不需要所有当前/下一个业务。 好吧,如果您愿意的话,您可以跟踪最新消息……但这是个主意。

如果您具有属性:

@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-最近beta版本中存在一些ARC错误。 如果是这样,您可以尝试使用最新的稳定版本进行构建,并查看是否获得更好的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM