1

I'm using the push handler of Core Motion for accelerometer updates:

CMAccelerometerHandler accelerometerHandler = ^ (CMAccelerometerData *accelerometerData, NSError *error) {
    // handle update
};

[motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue]
                                    withHandler:[[accelerometerHandler copy] autorelease]];

This code crashes. If I don't copy the block at all I get intermittent crashed on suspend/resume. If I remove the autorelease it works fine, but I think this will produce a leak.

I also tried to assign the block to an ivar and release it after [motionManager stopAccelerometerUpdates]. Crashes as well.

How comes? I always thought I've to balance any copy/retain with a release/autorelease?

See also: Copying blocks (ie: copying them to instance variables) in Objective-C

Community
  • 1
  • 1
Ortwin Gentz
  • 52,648
  • 24
  • 135
  • 213

1 Answers1

1

The issue here is ownership over the block. When you consider that blocks are really just objects it should become clearer how this all needs to work. You DO need to copy the block to the heap, but then you need to treat it just like every other object that you have ownership over. When the object that called copy on the block is dealloced, you should release your ownership over the block.

Joshua Weinberg
  • 28,598
  • 2
  • 97
  • 90
  • OK, stupid me. When I tried the ivar approach I described, I assigned the block literal to the ivar, then called `[motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:[[accelerometerHandler copy]]`. So when I released the ivar, I actually tried to release the stack block not the heap block. Which of course crashes. – Ortwin Gentz Nov 12 '10 at 18:36
  • That would cause problems :) Block management is a little odd sometimes, but you get the hang of it – Joshua Weinberg Nov 12 '10 at 18:38