Pass messages between two independent UIViews
What is the easiest way to 开发者_Python百科pass information between UIViews? If i have 2 standalone views that push and pop from the navigation bar and I want from one UIview to do some logic when a button pressed on the second UIview??
Is the right way is to use delegates? or is there a simple way with the interface builder? I know that I cannot drag button to action that is not on the same view in IB
thanks
You use the NSNotificationCenter to send messages to any other class that has registered an interested in that topic. Really easy :)
Notification Programming Guide
Here's the easiest thing. Ready to have your mind blown with how simple this can really be?
The following code demonstrates how to share a data object between two view controllers:
VCOne.h
@interface VCOne : UIViewController {
NSString *mystring;
}
@property (nonatomic, retain) NSString *mystring;
@end
VCOne.m
@implementation VCOne
@syntheize mystring;
-(void)viewDidLoad {
//you probably wouldn't do it here, but just so it has a
//place to live, I'm doing it in viewDidLoad...
VCTwo *two = [[VCTwo alloc] initWithNibName:@"VCTwoView" bundle:nil];
two.mystring = self.mystring;
[self.navigationController pushViewController:two animated:YES];
[two release];
}
-(void)dealloc {
[mystring release];
[super dealloc];
}
VCTwo.h:
@interface VCTwo : UIViewController {
NSString *mystring;
}
//nb the "assign" in the following line where you're probably
//used to seeing "retain"!!
@property (nonatomic, assign) NSString *mystring;
@end
VCTwo.m:
@implementation VCTwo
@synthesize mystring;
-(void)viewDidLoad {
self.mystring = @"I set this string inside VCTwo!";
}
-(void)dealloc {
[super dealloc];
}
Okay, so! One view controller has a NSString called *mystring and declares it as a @property with the retain
setter semantics. The second one has a NSString called *mystring and declares it as a @property with the assign
setter semantic (and, importantly, DOESN'T release it in -(void)dealloc
. This is memory-safe, although it does depend on the previous VC not releasing the object away from the current one!).
Then when the first VC instantiates the second one, it assigns its mystring field to the new VC's field. The new VC accepts that object and assigns it on its own @property
. Now anything you do to that variable in VCTwo is ALSO happening on the value that's referred to in VCOne. They're literally sharing that pointer now. Both view controllers have a handle on the same piece of memory.
Why not use retain
inside VCTwo? Because the setter method that's synthesized when you say retain
clears and resets the variable when it is set. They become separate objects, and they're not actually synced up. You can pass values between view controllers that way, but not references.
If you find yourself having issues with the object going away because it's getting released upstream (as a result of memory warnings, perhaps), you can always explicitly call [mystring retain]
and keep it around. Just be sure you DO release it in -(void)dealloc
if you do that.
The easiest way is to use delegate, init the secondViewController with:
UIViewController *secondVC = [[UIViewController alloc] initWithDelegate:firstVC callback:callback];
[firstVC.navigationController pushViewController:secondVC animated:YES];
This is exactly what the responder chain is meant for. Every UIView and UIViewController on the iPhone is a subclass of UIResponder. Additionally UIViews and UIViewControllers are both automatically added to the responder chain for you.
The responder chain is a way to send messages between responders. You can send messages to objects directly or you can pass them down the responder chain. This functionality is automatically implemented on UIButton's.
If you have a reference to view2 you can add view2 as a target of a button like so:
[button addTarget:view2 action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
If you do not have a reference you can add a target to a button like so:
[button addTarget:nil action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
Setting the target to nil means the action will be past down the responder chain until a responder is found that responds to the buttonClicked:
selector.
For more information take a look at UIControl documentation and UIResponder documentation.
I use NSUserDefaults
. You can save the specified Item in the App, launch it in the next view, and be able to launch it again if you go back to the first view! For example...
//Saving the file - use in the first view controller
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:somedataobject];
[prefs setObject:colordata forKey:@"DataKey"]
//Recalling the file - use in 2nd view
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSData *objectData = [prefs objectForKey:@"DataKey"];
Object *someobject = [NSKeyedUnarchiver unarchiveObjectWithData:objectData];
Now this is assuming that the data is NOT an NSInteger, an NSString, or a boolean value. In that case you would use:
[prefs setInteger: forKey:];
[prefs setBool: forKey:];
for the declaration, and
[prefs IntegerforKey:]
[prefs BoolforKey:]
for recalling.
The above syntax also works for doubles and floats
.
精彩评论