本文主要是介绍Passing Data between View Controllers,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
链接:http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers
1、
This question seems to be very popular here on stackoverflow so I thought I would try and give a better answer to help out people starting in the world of iOS like me.
I hope this answer is clear enough for people to understand and that I have not missed anything.
Passing Data Forward
Passing data forward to a view controller from another view controller. You would use this method if you wanted to pass an object/value from one view controller to another view controller that you may be pushing on to a navigation stack.
For this example we will have ViewControllerA
and ViewControllerB
To pass a BOOL
value from ViewControllerA
to ViewControllerB
we would do the following.
-
in
ViewControllerB.h
create a property for theBOOL
@property(nonatomic) BOOL *isSomethingEnabled;
-
in
ViewControllerA
you need to tell it aboutViewControllerB
so use an#import "ViewControllerB.h"
Then where you want to load the view eg.
didSelectRowAtIndex
or someIBAction
you need to set the property inViewControllerB
before you push it onto nav stack.ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil]; viewControllerB.isSomethingEnabled = YES; [self pushViewController:viewControllerB animated:YES];
This will set
isSomethingEnabled
inViewControllerB
toBOOL
valueYES
.
Passing Data Forward using Segues
If you are using Storyboards you are most likely using segues and will need this procedure to pass data forward. This is similar to the above but instead of passing the data before you push the view controller, you use a method called
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
So to pass a BOOL
from ViewControllerA
to ViewControllerB
we would do the following:
-
in
ViewControllerB.h
create a property for theBOOL
@property(nonatomic) BOOL *isSomethingEnabled;
-
in
ViewControllerA
you need to tell it aboutViewControllerB
so use an#import "ViewControllerB.h"
-
Create a the segue from
ViewControllerA
toViewControllerB
on the storyboard and give it an identifier, in this example we'll call it"showDetailSegue"
-
Next we need to add the method to
ViewControllerA
that is called when any segue is performed, because of this we need to detect which segue was called and then do something. In our example we will check for"showDetailSegue"
and if thats performed we will pass ourBOOL
value toViewControllerB
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{if([segue.identifier isEqualToString:@"showDetailSegue"]){ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController;controller.isSomethingEnabled = YES;} }
If you have your views embedded in a navigation controller you need to change the method above slightly to the following
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{if([segue.identifier isEqualToString:@"showDetailSegue"]){UINavigationController *navController = (UINavigationController *)segue.destinationViewController;ViewControllerB *controller = (ViewControllerB *)navController.topViewController;controller.isSomethingEnabled = YES;} }
This will set
isSomethingEnabled
inViewControllerB
toBOOL
valueYES
.
Passing Data Back
To pass data back from ViewControllerB
to ViewControllerA
you need to use Protocols and Delegates or Blocks, the latter can be used as a loosely coupled mechanism for callbacks.
To do this we will make ViewControllerA
a delegate of ViewControllerB
. This allows ViewControllerB
to send a message back to ViewControllerA
enabling us to send data back.
For ViewControllerA
to be delegate of ViewControllerB
it must conform to ViewControllerB
's protocol which we have to specify. This tells ViewControllerA
which methods it must implement.
-
In
ViewControllerB.h
, below the#import
, but above@interface
you specify the protocol.@class ViewControllerB;@protocol ViewControllerBDelegate <NSObject> - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item; @end
-
next still in the
ViewControllerB.h
you need to setup adelegate
property and synthesize inViewControllerB.m
@property (nonatomic, weak) id <ViewControllerBDelegate> delegate;
-
In
ViewControllerB
we call a message on thedelegate
when we pop the view controller.NSString *itemToPassBack = @"Pass this value back to ViewControllerA"; [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
-
That's it for
ViewControllerB
. Now inViewControllerA.h
, tellViewControllerA
to importViewControllerB
and conform to its protocol.#import "ViewControllerB.h"@interface ViewControllerA : UIViewController <ViewControllerBDelegate>
-
In
ViewControllerA.m
implement the following method from our protocol- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item {NSLog(@"This was returned from ViewControllerB %@",item); }
-
The last thing we need to do is tell
ViewControllerB
thatViewControllerA
is its delegate before we pushViewControllerB
on to nav stack.ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil]; viewControllerB.delegate = self [[self navigationController] pushViewController:viewControllerB animated:YES];
References
- Using Delegation to Communicate With Other View Controllers in the View Controller Programming Guide
- Delegate Pattern
2、
Passing data back from ViewController 2(destination) to viewController 1(Source) is the more interesting thing. Assuming you use storyBoard those are all the ways i found out:
- Delegate
- Notification
- User defaults
- Singleton
Those were discussed here already.
I found there are more ways:
-Using Block callbacks:
use it in the prepareForSegue
method in the VC1
NextViewController* destination = (NextViewController*) segue.destinationViewController;[destinationVC setDidFinishUsingBlockCallback:^(NextViewController *destinationVC){self.blockLabel.text = destination.blockTextField.text;}];
-Using storyboards Unwind (Exit)
Implement a method with a UIStoryboardSegue argument in VC 1, like this one:
-(IBAction)UnWindDone:(UIStoryboardSegue *)segue { }
In the storyBoard hook the "return" button to the green Exit button(Unwind) of the vc. Now you have a segue that "goes back" so u can use the destinationViewController property in the prepareForSegue of VC2 and change any property of VC1 before it goes back.
-
Another option of using storyboards Undwind (Exit) - you can use the method you wrote in VC1
-(IBAction)UnWindDone:(UIStoryboardSegue *)segue {NextViewController *nextViewController = segue.sourceViewController;self.unwindLabel.text = nextViewController.unwindPropertyPass; }
And in the prepareForSegue of VC1 you can change any property you want to share.
In both unwind options you can set the tag property of the button and check it in the prepareForSegue.
Hope i added something to the discussion.
:) Cheers.
这篇关于Passing Data between View Controllers的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!