Search code examples
iosobjective-cuiviewuislideruibezierpath

Get the current value of UISlider in drawRect: method


I'm trying to move a point drawn in a UIView based on the value of a UISlider. The code below is for a UIView (subview ?) with a custom class (WindowView) on a UIViewController.

WindowView.h

#import <UIKit/UIKit.h>

@interface WindowView : UIView

- (IBAction)sliderValue:(UISlider *)sender;

@property (weak, nonatomic) IBOutlet UILabel *windowLabel;


@end

WindowView.m

#import "WindowView.h"

@interface WindowView ()
{
    float myVal; // I thought my solution was using an iVar but I think I am wrong
}

@end

@implementation WindowView

@synthesize windowLabel;
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)sliderValue:(UISlider *)sender
{
    myVal = sender.value;
    windowLabel.text = [NSString stringWithFormat:@"%f", myVal];
}

- (void)drawRect:(CGRect)rect
{
    // I need to get the current value of the slider in drawRect: and update the position of the circle as the slider moves
    UIBezierPath *circle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(myVal, myVal, 10, 10)];
    [circle fill];
}

@end

Solution

  • OK, you need to store the slider value in an instance variable and then force the view to redraw.

    WindowView.h:

    #import <UIKit/UIKit.h>
    
    @interface WindowView : UIView
    {
        float _sliderValue;   // Current value of the slider
    }
    
    // This should be called sliderValueChanged
    - (IBAction)sliderValue:(UISlider *)sender;
    
    @property (weak, nonatomic) IBOutlet UILabel *windowLabel;
    @end
    

    WindowView.m (modified methods only):

    // This should be called sliderValueChanged
    - (void)sliderValue:(UISlider *)sender
    {
        _sliderValue = sender.value;
        [self setNeedsDisplay];   // Force redraw
    }
    
    - (void)drawRect:(CGRect)rect
    {
        UIBezierPath *circle = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(_sliderValue, _sliderValue, 10, 10)];
        [circle fill];
    }
    

    You probably want to initialise _sliderValue to something useful in the view's init method.

    Also _sliderValue probably isn't the name you want to choose; perhaps something like _circleOffset or some such.