Reputation: 273
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
Reputation: 6187
A few things I am noticing in your code:
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)
Upvotes: 0
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