Search code examples
iosobjective-cuiviewuislider

How can I tap into a UIView's changing values during an animateWithDuration block?


I am using animateWithDuration to change the value of a UISlider:

[UIView animateWithDuration:1.0f
                      delay:0.0f
                    options:UIViewAnimationOptionCurveEaseInOut
                 animations:^{ [myUISlider setValue:10]; }
                 completion:^(BOOL finished){ }];

The problem is, I need to be able to display the current value of the UISlider while it is changing. Is this even possible using animateWithDuration? I tried creating a UISlider subclass and overriding setValue in hopes of getting access to the slider's value as it is being changed:

-(void)setValue:(float)newValue
{
    [super setValue:newValue];

    NSLog(@"The new value is: %f",newValue);
}

But that code only gets called at the very end of the animation block. In a way that makes perfect sense, since I really only called setValue once. But I was hoping that the animation block would somehow call it over and over again within its internal mechanisms, but that appears not to be the case.

If UIView animateWithDuration is a dead-end here, I wonder if there is a better way to acheive this same functionality with something else? Perhaps another slick little block-driven part of the SDK I don't know about which allows animating more than just UIView parameters?


Solution

  • I think the best way is to handle it is to code a custom Slide you can creat it like progress bar which there are many demo on github.

    You can also use NSTimer to do it , but I do not think it is a very better way.

    When you tap , you can creat a timer :

    _timer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(setValueAnimation) userInfo:nil repeats:YES];

    and set a ivar: _value = oldValue;

    in the setValueAnimation method :

    - (void)setValueAnimation
    {
        if (_value >= newValue) {
            [_timer invalidate];
            _value = newValue;
            [self setVale:_value];
            return;
        }
    
        _value += .05;
    
        [self setVale:_value];
    
    }
    

    UPDATE

    how to add block:

    1st:you can define a block handler :

    typedef void (^CompleteHandler)();
    

    2nd: creat your block and added it into the userInfo :

    CompleteHandler block = ^(){
        NSLog(@"Complete");
    };
    
    NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:block,@"block", nil];
    

    3rd: make the NSTimer:

    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(setValueAnimation:) userInfo:userInfo repeats:YES];
    

    4th:achieve your timer method:

    - (void)setValueAnimation:(NSTimer *)timer
    {
        if (_value >= newValue) {
            [_timer invalidate];
            _value = newValue;
            [self setVale:_value];
    
            // also can use [_delegate complete];
    
            CompleteHandler block = [timer.userInfo objectForKey:@"block"];
            if (block) {
    
                  block();
    
            }
            return;
        }
    
        _value += .05;
    
        [self setVale:_value];
    
    }