Search code examples
objective-cshakecore-motion

Adapting Shake Code from 'Beginning Iphone 4 Development' Causing Crash


The code below is a near replica of the Shake and Bake example from Beginning Iphone 4 Development. It is lacking a BOOL if statement before CMAcceleration acceleration = accelerometerData.acceleration; because I want the person to shake and refresh the results as many times as they want. I have a button that executes the same code flawlessly. When I run the code and shake the iphone, it crashes. What am I missing that will make this work? Can you not run the same code with a button as with the shake method?

Example.h

#import <CoreMotion/CoreMotion.h>
#define kAccelerationThreshold 1.7
#define kUpdateInterval (1.0f/10.0f)

@interface exampleViewController : UIViewController  {
CMMotionManager *motionManager;
}
@property (retain,nonatomic) CMMotionManager *motionManager;
@end

Example.m

@synthesize motionManager;

-(void)viewDidLoad {

self.motionManager = [[[CMMotionManager alloc] init] autorelease];
motionManager.accelerometerUpdateInterval = kUpdateInterval;
NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
[motionManager startAccelerometerUpdatesToQueue:queue
                                    withHandler:
 ^(CMAccelerometerData *accelerometerData, NSError *error){
     if (error) {
         [motionManager stopAccelerometerUpdates];
     } else {
         CMAcceleration acceleration = accelerometerData.acceleration;
         if (acceleration.x > kAccelerationThreshold 
            || acceleration.y > kAccelerationThreshold 
            || acceleration.z > kAccelerationThreshold){

// There is a bunch of other stuff here, but it all works using a button called shake....
            example4.hidden = NO;
            select1.text = first;
            display.text = [[NSString alloc] initWithFormat: @"%@", first];

         }
     }
 }];
}

- (void)dealloc
{
[super dealloc];
[motionManager release];
}

- (void)viewDidUnload {
[super viewDidUnload];
self.motionManager = nil;
}

@end

Solution

  • You are trying to create and display an alert view on a thread other than the main thread. UI updates are to be done in the main thread only. You should use performSelectorOnMainThread:withObject:waitUntilDone: to create and display on the main thread.

    You can always add a request your UI updates like this –

    dispatch_async(dispatch_get_main_queue(),^{
        // Put all your UI updates here; 
    });