Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setNeedsDisplay not working inside a block

I'm using CMMotionManager for retrieving accelerometer data. The thing is that the accelerometer data gets printed periodically, the instance variables are changed in the view, but the view doesn't get redrawn. I have checked that hv is not nil and that everything is hooked. Is there a problem with calling setNeedsDisplay within a block?

-(void) viewDidAppear:(BOOL) animated
{
    [super viewDidAppear: animated];

    [motionManager startAccelerometerUpdatesToQueue:motionQueue withHandler:
     ^(CMAccelerometerData *accelerometerData, NSError *error)
    {

        NSLog(@"%@",accelerometerData);

        HypnosisView *hv = (HypnosisView *) [self view];

        hv.xShift = 10.0 * accelerometerData.acceleration.x;
        hv.yShift = -10.0 * accelerometerData.acceleration.y;

        [hv setNeedsDisplay];

    }];    
}
like image 770
jorurmol Avatar asked Nov 29 '11 15:11

jorurmol


2 Answers

It's because your calling a UI method on a thread different from the main thread.

Add this to your block:

dispatch_async(dispatch_get_main_queue(), ^{
    [hv setNeedsDisplay];
});

Remember that any method dealing with user interface elements must be called from the main thread.

like image 96
cocoahero Avatar answered Oct 23 '22 19:10

cocoahero


I have done the same in other blocks and it did work, though not with the callback you use here. Maybe the block is not executed on the main thread? You can check that with:

NSLog(@"Main thread? %d", [NSThread isMainThread]);

If it is not, you could force setNeedsDisplay to run on the main thread.

like image 26
Pascal Avatar answered Oct 23 '22 20:10

Pascal