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 fl开发者_如何学Goawlessly. 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
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;
});
The part that looks fishy to me is NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
.
Nowhere are you hanging on to the queue for the duration of the time that motionManager is dispatching to it. I checked the documentation for startAccelerometerUpdatesToQueue
but it doesn't say that the receiver retains the queue, so that's probably not something you can safely assume. My suggestion is to not autorelease the queue. Instead, release it in viewDidUnload
after calling stopAccelerometerUpdates
on motionManager.
精彩评论