Old Name
Old Name

Reputation: 273

UISlider value is zero when trying to pass value to UIView with custom class

I have a UIView, UILabel, and UISlider placed in my UIVeiwController in my ViewController files. I have also programmatically added a UILabel to the UIView as a debugging tool.

Yes, I could connect to the UILabel within the UIView the same as I have for the other UILabel but once I solve this problem I will be passing this value in the graph calculation. I'm open to any suggestion for passing this variable to my UIView but would prefer to avoid creating global variables. I'm passing my UISlider value to the UILabel placed in my UIVeiwController as it should but when I try to send the value by "referencing" the slider value in my GraphView.m implementation file it never makes it and I'm getting a value of zero.

I've spent two days scouring stackoverflow forums, reviewing documentation, and re-reading books trying to figure out my issue and while I've learned a great deal (and fixed other problems) I've still not figured this one out. I'm sure its something so simple and I'm sure gonna kick myself. I welcome your references to other documentation (I've probably already read it) but please offer some constructive feedback and direction as well. My code is below:

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    NSString *viewControllerSliderValue;
}
- (NSString *) viewConrtollerSliderValue;

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

@property (weak, nonatomic) IBOutlet UISlider *sliderValue;

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

@end

ViewController.m

#import "ViewController.h"
#import "GraphView.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    float sliderVal = self.sliderValue.value;
    self.sliderValueLabel.text = [NSString stringWithFormat:@"%.1f",sliderVal];
    NSLog(@"viewDidLoad: sliderVal = %f", sliderVal);
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)sliderChange:(UISlider *)sender
{
    float sliderVal = sender.value;
    self.sliderValueLabel.text = [NSString stringWithFormat:@"%.1f", sliderVal];
    NSLog(@"sliderChange: sliderVal = %f", sliderVal);

}

- (NSString *)viewConrtollerSliderValue
{
    float sliderVal = self.sliderValue.value;
    viewControllerSliderValue = [NSString stringWithFormat:@"%f",[self sliderValue].value];
    NSLog(@"sliderChange: sliderVal = %f", sliderVal);
    return viewControllerSliderValue;
}

@end

GraphView.h

#import <UIKit/UIKit.h>

@interface GraphView : UIView

@end

GraphView.m

#import "GraphView.h"
#import "ViewController.h"

@implementation GraphView

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

- (void)drawRect:(CGRect)rect
{
    ViewController *viewController = [[ViewController alloc] init];

    UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(30, 90, 140, 20)];
    NSLog(@"GraphView: drawRect: vierContrllerSliderValue = %@", [viewController viewConrtollerSliderValue]);
    myLabel.text = [viewController viewConrtollerSliderValue];
    myLabel.backgroundColor = [UIColor lightGrayColor];
    myLabel.textAlignment = NSTextAlignmentCenter;
    [self addSubview:myLabel];
}

@end

Upvotes: 0

Views: 582

Answers (2)

BergQuester
BergQuester

Reputation: 6187

A few things I am noticing in your code:

  • Everything in your drawRect: method should never be done in a drawRect:. drawRect: should only be used to draw pixels on the screen (using bezier paths, colors, etc.). drawRect: can be called many times per second, so it is important that it be as fast as possible. As such, creating objects and manipulating the view hierarchy should never be done. Creating ViewControllers in a drawRect: should never be done.

If you need to setup the initial state of views, that should be done in the view controller's viewDidLoad method. You probably want to create the GraphView in the xib and create an outlet connection to the view controller. You can do this by adding a new UIView to your xib and editing the Class in the Identity inspector in the right-hand sidebar as shown below. (you may also programmatically create the GraphView using initWithFrame: and adding it as a subview of the view controller's view)

enter image description here

Upvotes: 0

BJ Homer
BJ Homer

Reputation: 49044

The problem is that your GraphView is creating a new view controller when it calls ViewController *viewController = [[ViewController alloc] init];, which is separate from the one being displayed on the screen. That new controller's slider isn't the one you're manipulating, so it's never changing values.

An additional problem is that your GraphView is adding a new label every time you call drawRect:. That method is called every time the view needs to be re-drawn. Instead, add the label as a subview in the -initWithFrame: method, and keep a reference to it as an instance variable or a property.

It would be better for the GraphView to never know about a view controller at all. Instead, the GraphView should simply have a setter method to set the value that should be displayed. The controller should be responsible for telling the graph view to update whenever the slider changes. It would look something like this:

@interface GraphView
@property (nonatomic) float graphValue;
@end

@implementation GraphView {
    UILabel *graphLabel;
}


- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        graphLabel = [[UILabel alloc] initWithFrame:CGRectMake(30, 90, 140, 20)];
        graphLabel.backgroundColor = [UIColor lightGrayColor];
        graphLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:graphLabel];
    }
    return self;
}


- (void)setGraphValue:(float)theValue {
    _graphValue = theValue;
    graphLabel.text = [NSString stringWithFormat:@"%f", theValue]
}

// Note; no need for -drawRect, because it will all be drawn by the label, which is a subview.

@end

Upvotes: 1

Related Questions