I have an UITabBarController
with two tabs:
UINavigationController
OptionsViewController : UIViewController
I have an easy way to access data between views. Let's try. You have two views named view1 and view2, you can define a View *vc1 property in view2.h, set the vc1 point to view1, when pop the view2, like this:
view1.m
//here pop out view1 code View2 *view2 = [[View2 alloc] initWithNibName:@"View2" bundle:[NSBundle mainBundle]]; [self.navigationController pushViewController:view2 animated:YES]; view2.vc1 = self; //transfer view1 instance to view2,use vc1 you may handle view1 in view2 directly [view2 release];
view2.h
#import "view1.h" @property (nonatomic, retain) IBOutlet View1 *vc1; //here you could name it as view1 as well :)
view2.m
vc1.lblTable.text = @"ok"; //you'll see "ok" in view1 [self.navigationController popViewControllerAnimated:YES]; //navigate to view1
//dont forget release vc1
I usually set IBOutlets in each of my viewcontrollers which point to the other controller. So if I had view controllers A and B. A has an IBOutlet to B and B to A. Then whenever I want to access anything in B from A i just use a dot operator on B.
In your example UINavigationController would #include "OptionsViewController.h"
and have an ivar IBOutlet OptionsViewController * ovc
(which is set in IB) and then any instance variable from your options view controller can be referenced as ovc.UILabel.text
from the navigation controller. This process can be reversed to access values from your navigation controller in your options view controller.
Example Navigation Controller (.h):
#include "OptionsViewController.h"
@interface UINavigationController // (whatever the name of this class is)
{
OptionsViewController * ovc;
}
@property (nonatomic, retain) IBOutlet OptionsViewController * ovc;
@end
Example OptionsViewController.h:
@interface OptionsViewController
{
UILabel * label;
}
@property (nonatomic, retain) IBOutlet UILabel * label;
@end
Then from UINavigationController (.m) you can just write ovc.label.text
to access the text.
I love MVC, but I'm not an absolute purist to the point of hurting yourself to accomplish a fairly trivial task, so the answers you've gotten here are good and useful. However, by creating an ivar to refer back to a specific type such as a label or other view controller, you are coupling things together that aren't necessary to couple. What you could do instead is make your first tab view controller a delegate of your second tab view controller. So do something like this in your app delegate.
OptionsViewController *optionsViewController = // ... get this from the tab view
FirsTabViewController *firstTabViewController = // ... same here
[optionsViewController setDelegate:firsTabViewController];
Which means that you need an ivar in your OptionsViewController:
@property (assign) id delegate;
Then, when whatever event you want to trigger the change occurs in your options view controller, see if the delegate can respond to a selector you've named. For example:
- (void)someEventHappenedLikeTyping:(id)sender;
{
if ([delegate respondsToSelector:@selector(setOptionsString:)]
[delegate performSelector:@selector(setOptionsString:) withObject:[label text]];
}
Notice you never specified any specific object types. You just check to see if the delegate (which was declared as id) can respond to that selector. If it can, it does what it's told and just is silent otherwise.
For this to work, you need an ivar for the optionsString in your FirstTabViewController and so it would be declared in the header as:
@property (copy) NSString *optionsString;
and then @synthesize it in the .m. This causes -setOptionsString to become a valid selector that will get called in the -someEventHappenedLikeTyping method.
Anyhow, now, if you ever need to to change which view controller references which, you don't have to go into the header and change the type of ivar referenced. You simply need to implement the selector (this is known as an informal protocol, by the way) in the view controller that is a delegate of your options view controller.
Just some food for thought there. Hope that helps. There is further de-coupling that could be done in the code I've added, but again it may be overkill for such a simple task. Let me know if you need clarification or want to understand what I mean by further decoupling.
Best regards,
p.s. Sometimes needing to share data between two tab bar view controllers, means you have a design flaw. If you are wanting to store preferences from your options view, you should just call
[[NSUserDefaults standardUserDefaults] setObject:[label text] forKey:@"option1"];
[[NSUserDefaults standardUserDefaults] synchronize];
Then you can pull from the NSUserDefaults back in your main tab with;
NSString *option1 = [[NSUserDefaults standardUserDefaults] objectForKey:@"option1"];
// Do something with option1
In your OptionsViewController, create a property:
@property (nonatomic, retain) UILabel *mylabel;
then after creating your OptionsViewController
, but before displaying it, set the mylabel
property. (Or perhaps you just want the text, so you can use an NSString*
property.)
Edit:
So you probably want to do something like this:
OptionsViewController *vc = [[OptionsViewController alloc] init];
vc.mylabel = mySomethingLabel;
[self presentModalViewController:vc animated:YES];
So after creating the object, you set the property, and then you display the view controller.