Search code examples
objective-canimationif-statementnsuinteger

Does a value update inside a block/completion block, if changed in a different thread?


I have a UIView animateWithDuration (in a method being called by a button) that animates a UIImageViews. The important code before the animation code: (the title is appropriate, just keep reading)

//Sets _squareOneNumber to 0 (this is going to be the changing value)
_squareOneNumber = 0;

Basically the animation code just allows user interaction and animates the image to down the screen at a random pace.

But, it's the completion block that is killing me (don't worry about a and b):

if (self.squareOneNumber==0) {
    if (a==b) {
        [self gameOverImagePutter];
        NSLog(@"One wasn't pressed");
    }
}

The value of _squareOneNumber changes to 1 if it is pressed.

//In touchesBegan method
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];

if ([self.squareOne.layer.presentationLayer hitTest:touchLocation]) {
    [_squareOne setHidden:YES];
    _squareOneNumber = 1;
}

The completion block should call gameOverImagePutter if squareOne wasn't pressed (squareOneNumber=0) and a==b. But it is always called when squareOne is pressed (squareOneNumber=1). To me, the code should work fine. But I think the issue is that squareOneNumber isn't getting updated even though its value has changed.

So basically this is my question:

  • how to I get the code to work?
  • why isn't squareOneNumber realizing it's value has changed?

Solution

  • i recreated the code that i think you have from what you posted and it does work as expected. squareOneNumber is updated when completion block executes. The image is on screen, when the button is pressed image starts moving. When you press on the image it is hidden and squareOneNumber is set to 1. Then in few seconds completion block is being executed with the update value.

    The only way that won't work if you press the button again and the animation is running with the hidden image and squareOneNumber resets to 0 which will be reflected in the completion block. Here is my code. Let me know if i correctly recreated your part of the code.

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet UIImageView *squareOne;
    @property (nonatomic) NSUInteger squareOneNumber;
    @end
    
    @implementation ViewController
    - (IBAction)animateImage:(id)sender
    {
        [UIView animateWithDuration:4.0 animations:^{
            self.squareOneNumber = 0;
            self.squareOne.center = CGPointMake(300, 300);
    
        } completion:^(BOOL finished) {
            NSLog(@"square one in completion %lu",self.squareOneNumber);
            if (self.squareOneNumber == 0) {
                NSLog(@"0");
            }else{
                NSLog(@"1");
            }
    
        }];
    
    }
    
    
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        UITouch *touch = [touches anyObject];
        CGPoint touchLocation = [touch locationInView:self.view];
    
        if ([self.squareOne.layer.presentationLayer hitTest:touchLocation]) {
            [self.squareOne setHidden:YES];
            self.squareOneNumber = 1;
            NSLog(@"square one in touches began %lu",self.squareOneNumber);
        }
    }
    
    @end
    

    Here is the NSLog output when imageView is pressed

    2014-11-30 23:14:30.541 StackOveflowAnimation[3885:1092103] square one in touches began 1
    2014-11-30 23:14:33.356 StackOveflowAnimation[3885:1092103] square one in completion 1
    2014-11-30 23:14:33.356 StackOveflowAnimation[3885:1092103] 1