I have browsed through a lot of the "pass data between view controller" questions. But I can't seem to grasp the concept of passing data.
Why is it such a hassle to get user- or system generated value's from one view to another?
I'm new to Objective-C, but I have done some programming before in my life so I'm not unfamiliar with all the terminologies.
I have read about delegate's, protocols, singletons and segue's. I have tried to experiment with example files but could not recycle the codes to my needs nor do I understand what processes it takes to pass data.
What I'm trying to learn is how I can pass all the generated data from 1 UIViewController to multiple UIViews. All the value's I generate need to be able to update instantaneously and be accesible without requiring a view switch nor does a button press be required to update/pass the data trough.
Can someone please explain me once and for all how to pass data between different header files and UIViews. It is driving me nuts, I just want the data to be there and accessible whenever and where ever I need it.
This is what i'm trying to create,
I got three sliders each representing an axis.
The user can create two keyframes based on the values they use with the sliders.
These values get saved (in the UIViewControler.m) and create a visual keyframe(UIImage) on screen.
Keyframe 1 and keyframe 2, these keyframes will be used as CGPoints for a UIBezierCurve.
That being said, I dragged an UIView into my UIViewController and linked the UIView to my "BezierGraphView.h".
Now i need to pass these keyframe points to the BezierGraphView. How would i do this?
In iOS, a lot of time is spent in ViewControllers.
View Controllers are vitally important for two main reasons:
- They have references to view objects on the screen (i.e. self.loginButton is referring to a UIButton that the View Controller has access to)
- They are aware of the data model. (i.e. there are references to data that is relevant for the screen)
Theres two different types of data passing. Theres passing data objects from UIViewController to a different UIViewController [explained beautifully here: Passing Data Objects]. Then theres the method where a UIViewController uses the data object to display information on the screen.
So in order to have a UIViewController effect something on the screen you need to:
- Have a data object (an array, a custom object, anything really)
- Have a reference to a view (a UILabel, UIButton, etc)
For example here is how you can generate and use temp data to display information on the screen. Assume there is a User object and a UserNameLabel;
- (id)init {
if (self = [super init]) {
self.user = [User newUserWithTempData];
}
return self;
}
Then in the viewDidLoad method :
- (void)viewDidLoad
{
[super viewDidLoad];
self.userNameLabel.text = self.user.nameString;
}
This handles using data to affect views on the screen. If you're asking about how to share the User object between different View Controllers, then that is a different issue which I can explain if you'd like.
Edit: I'm assuming your question is asking how to get a reference to a view from storyboard.
I'll explain everything in this image step by step as it will hopefully walk you through the steps to put it all together. I'll break it up based on what the numbered arrows refer to. Here we go:
Arrow 1
Arrow 1 is pointing to the Document Outline of a xib of a UITableViewCell subclass.
Note: CircleView is a custom subclass of UIView. With the following implementation:
#import "CircleView.h"
@implementation CircleView
- (void)drawRect:(CGRect)rect{
// CUSTOM DRAWING METHOD HERE
}
@end
Arrow 1 is pointing to the custom CircleView view on the screen. To do this, I add a UIView to the screen and then change the class.
Arrow 2
Arrow 2 is pointing to how to change a view in Storyboard or Interface Builder to a custom view that has a custom implementation. Here, simply have the view selected and open the file inspector on it. Then find this tab and change the custom class from UIView to MyCustomView.
Arrow 3
Arrow 3 is pointing to the property that relates to the custom view in the Interface Builder.
Here's the code of it:
#import <UIKit/UIKit.h>
@class CircleView;
@interface CreateNewQuestionCell : UITableViewCell
@property (nonatomic, weak) IBOutlet CircleView *circleView;
@end
Here is where you declare the property, using the custom class that you created. Make sure to have IBOutlet so that Xcode can allow the next step to work :)
Arrow 4
Arrow 4 is pointing to an indicator that tells you whether or not properties are on a view from storyboard are connected to the property in the class. This is how you ensure everything is wired up.
Theres 2 ways to do this, I'll show the quick way, but if you're curious let me know and I'll add more.
- Click on the indicator and drag to the custom view you created and release. [BTW, to get 2 screens open, open the Assistant Editor ]
Here is a snapshot:
Complete
Now when I run the app, that view is now a Circle View, a custom class that draws a shaded circle in the area.
And at this point, you can change anything you need to in the viewDidLoad function.
Edit for clarification:
This is how you can send the data from your controls (the sliders) to other .h's, as you put it, the UIView. When sending data between multiple UIViewControllers you do so on segues and through delegate methods. The BezierGraphView is a View, not a ViewController. As someone suggested in a comment, I'd do a little research on the MVC (Model-View-Controller) paradigm.
It seems like you have a single UIViewController with four subviews. Three UISliders, and a BezierGraphView that has some custom drawRect code. If you want to send the slider values to the BezierGraphView when it changes, do something like this:
First, make sure you have an outlet for your BezierGraphView and your sliders in your UIViewController.
Second, create an action for your slider's Value Changed control, and hook all three up to it.
// MyUIViewController.h
#import <UIKit/UIKit.h>
#import "BezierGraphView.h"
@interface MyUIViewController : UIViewController
@property (nonatomic, strong) IBOutlet BezierGraphView *graphView;
@property (strong) IBOutlet UISlider *xSlider;
@property (strong) IBOutlet UISlider *ySlider;
@property (strong) IBOutlet UISlider *zSlider;
-(IBAction)sliderValueDidChange;
@end
Then move your BezierGraphView's drawRect code to a function:
//BezierGraphView.h
#import <UIKit/UIKit.h>
@interface BezierGraphView : UIView
-(void)valuesDidChangeWithX:(CGFloat)xValue Y:(CGFloat)yValue Z:(CGFloat)zValue;
@end
//BezierGraphView.m
#import "BezierGraphView.h"
@implementation BezierGraphView
-(void)valuesDidChangeWithX:(CGFloat)xValue Y:(CGFloat)yValue Z:(CGFloat)zValue{
//drawRect code goes here
}
@end
Then whenever a slider's value changes, it will tell the UIViewController in sliderValueDidChange, and you can tell the BezierGraphView to update with the valuesDidChangeWithX: Y: Z: method:
//MyUIViewController.m
@implementation MyUIViewController
//Other UIViewController stuff, like viewDidLoad
-(IBAction)sliderValueDidChange{
[self.graphView valuesDidChangeWithX:self.xSlider.value
Y:self.ySlider.value
Z:self.zSlider.value]
}
@end