0

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
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Old Name
  • 273
  • 1
  • 3
  • 13
  • You can't call like this , It may be deallocate once you left the viewController . assign the SliderValue from viewController to one of the var at Graph. – Kumar KL May 21 '13 at 04:43

2 Answers2

1

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
BJ Homer
  • 48,806
  • 11
  • 116
  • 129
  • I understand this is probably very basic but I'm "new." Can you elaborate on what you've done and how this works? I've followed and read many book/documentation/resources but I just haven't reached that "Ah-ha" moment yet. Also, since I added the GraphView UIView through the Interface Builder should I add the content above to initWithCoder: instead of initWithFrame? I also don't understand where setGraphValue: comes from. How do I create this? – Old Name May 21 '13 at 22:38
  • OK, I think what you described above is similar to how I solved my issue... I just did it in a little different manner. I created an IBAction for my UISlider in my GraphView (the same as I did in ViewController) and then linked it in the Interface Builder... Now it works as expected. – Old Name May 21 '13 at 22:54
0

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

BergQuester
  • 6,167
  • 27
  • 39
  • There's nothing wrong with the outlets being weak. Outlets are normally weak, because the view that contains them keeps a strong pointer to them. – rdelmar May 21 '13 at 06:41
  • Upon [further reading](http://stackoverflow.com/questions/7678469/should-iboutlets-be-strong-or-weak-under-arc) it seems that you are correct. I thought that when creating an IBOutlet in the header by dragging a connection from Interface Builder created a strong reference by default, that is not necessarily the case. Thank you for brining this to my attention. – BergQuester May 21 '13 at 16:42
  • @BergQuester I understand what your saying about drawRect: and ultimately my intention is to draw a bezier path as the representation of my line graph. the only reason I created a label in this manner is to debug, so that I had an outlet to see what value was being passed. Also the method you described about adding the GraphView above is exactly the process I used to add it and then changed the in the identity inspector. – Old Name May 21 '13 at 22:31