jorurmol
jorurmol

Reputation: 117

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

    }];    
}

Upvotes: 7

Views: 2216

Answers (3)

Newbie indeed
Newbie indeed

Reputation: 87

Just wanted to test @cocoahero's answer. I tried to call setTitle for a UIButton in a non main thread. And the title did changed. I tried this both targeting iOS 5.1 and 7.0 using Xcode 5.0.1. Also I called setNeedsDisplay from a non main thread and it worked too.

[NSThread isMainThread] was how I made sure that my calls were not from main thread. I am not sure calling from non main thread was the cause to your problem but at least there are other possibilities there. You can take a look at my answer for another question.

Upvotes: 0

cocoahero
cocoahero

Reputation: 1302

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.

Upvotes: 12

Pascal
Pascal

Reputation: 16941

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.

Upvotes: 4

Related Questions