简体   繁体   中英

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

There is a gap in my understanding of blocks and ARC that I would like some help with. I have received a crash report from a tester which originates from an animation completion block. The crash is as follows:

Exception Type: EXC_BAD_ACCESS (SIGSEGV)

Exception Codes: KERN_INVALID_ADDRESS at 0xf0000010

This is happening inside the following animation completion block (using animateWithDuration:animations:completion: ). I am swapping two view controllers using a temporary variable:

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

next = temp; is the line on which the crash occurs. The duration of the animation is 0.3 seconds.

This code is executed inside a view controller which acts as a container for two other view controllers, used to simulate the user passing through a list of objects, like a navigation controller, but with a number of customisations that meant a navigation controller was not appropriate for me.

The two child view controllers are called "current" and "next" - as you can guess the current controller displays the current content, and the next one is used to animate in the new item when the user moves through the list.

If I change the block so that temp is declared in the implementation (along with current and next ) the crash stops. However it seems unnecessary to me to have to hold a class ivar for something that is by definition local and temporary.

So,

  • Why is temp apparently released by ARC during this process?
  • What would be the correct way to implement this? Is there some lifetime qualifier I should add to the block implementation?
  • Why could I not reproduce the crash on my own device or in the simulator? Both devices were iPhone 4 running the same version of iOS (5.0.1).

I don't think the problem is actually ARC in this instance. Variables (including local variables) are __strong by default, so current should be retained in the first assignment.

http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/_index.html - see section 'Variable Qualifiers'

If you've got a crash you can't reproduce yourself, it's always going to be difficult to fix. Have you tried running the app outside of the debugger? Having the debugger loaded can sometimes change behaviour. Also, try debugging with NSZombieEnabled, or Instruments.app's zombie tool.

And if it really keeps you up, since you're only alternating between two views you don't actually need all this current / next business. Well, you can keep track of current if you want... but here's the idea.

If you have properties:

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

Then you can have a method:

- (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;
                     }];
}

As for your original issue, ARC knows how to handle blocks pretty well - if you weren't using it, I might ask if you'd forgotten to copy a block declared elsewhere, then stored, then passed in as the completion handler. Since that's not the case, and since you haven't been able to get a repro... I'm guessing that you might be running a beta sdk - there have been some ARC bugs in beta releases of late. If that's so, you might try building with the last stable release, and see if you get better results.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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