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.
(这个问题在stackoverflow上似乎很受欢迎,所以我想我会尝试给出一个更好的答案来帮助像我这样的iOS初学者。)
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
(对于此示例,我们将有ViewControllerA
和ViewControllerB
)
To pass a BOOL
value from ViewControllerA
to ViewControllerB
we would do the following.
(要将BOOL
值从ViewControllerA
传递到ViewControllerB
我们需要执行以下操作。)
in ViewControllerB.h
create a property for the BOOL
(在ViewControllerB.h
为BOOL
创建一个属性)
@property (nonatomic, assign) BOOL isSomethingEnabled;
in ViewControllerA
you need to tell it about ViewControllerB
so use an
(在ViewControllerA
您需要向其介绍ViewControllerB
因此请使用)
#import "ViewControllerB.h"
Then where you want to load the view eg.
(然后在你想加载视图的地方。)
didSelectRowAtIndex
or some IBAction
you need to set the property in ViewControllerB
before you push it onto nav stack. (didSelectRowAtIndex
或某些IBAction
,需要先在ViewControllerB
设置该属性,然后再将其推入导航堆栈。)
ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil]; viewControllerB.isSomethingEnabled = YES; [self pushViewController:viewControllerB animated:YES];
This will set isSomethingEnabled
in ViewControllerB
to BOOL
value YES
.
(这会将ViewControllerB
isSomethingEnabled
设置为BOOL
值YES
。)
Passing Data Forward using Segues
(使用Segues转发数据)
If you are using Storyboards you are most likely using segues and will need this procedure to pass data forward.
(如果使用情节提要,则很有可能使用segues,并且需要此过程将数据转发。)
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:
(因此,要将BOOL
从ViewControllerA
传递到ViewControllerB
我们需要执行以下操作:)
in ViewControllerB.h
create a property for the BOOL
(在ViewControllerB.h
为BOOL
创建一个属性)
@property (nonatomic, assign) BOOL isSomethingEnabled;
in ViewControllerA
you need to tell it about ViewControllerB
so use an
(在ViewControllerA
您需要向其介绍ViewControllerB
因此请使用)
#import "ViewControllerB.h"
Create a the segue from ViewControllerA
to ViewControllerB
on the storyboard and give it an identifier, in this example we'll call it "showDetailSegue"
(在情节ViewControllerB
上从ViewControllerA
到ViewControllerB
创建一个序列,并为其指定一个标识符,在本示例中,我们将其称为"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.
(接下来,我们需要将方法添加到执行任何segue时要调用的ViewControllerA
中,因此,我们需要检测调用了哪个segue,然后执行某些操作。)
In our example we will check for "showDetailSegue"
and if that's performed we will pass our BOOL
value to ViewControllerB
(在我们的示例中,我们将检查"showDetailSegue"
,如果执行了此操作,则将BOOL
值传递给ViewControllerB
)
-(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
in ViewControllerB
to BOOL
value YES
.
(这会将ViewControllerB
isSomethingEnabled
设置为BOOL
值YES
。)
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.
(通过从数据回ViewControllerB
到ViewControllerA
需要使用协议和代表或块 ,后者可以被用作用于回调松散耦合机制。)
To do this we will make ViewControllerA
a delegate of ViewControllerB
.
(要做到这一点,我们将ViewControllerA
的委托ViewControllerB
。)
This allows ViewControllerB
to send a message back to ViewControllerA
enabling us to send data back. (这使ViewControllerB
可以将消息发送回ViewControllerA
从而使我们能够将数据发送回去。)
For ViewControllerA
to be a delegate of ViewControllerB
it must conform to ViewControllerB
's protocol which we have to specify.
(对于ViewControllerA
是的委托ViewControllerB
它必须符合ViewControllerB
我们有指定的协议。)
This tells ViewControllerA
which methods it must implement. (这告诉ViewControllerA
它必须实现哪些方法。)
In ViewControllerB.h
, below the #import
, but above @interface
you specify the protocol.
(在ViewControllerB.h
,在#import
下方,但在@interface
上方,指定协议。)
@class ViewControllerB; @protocol ViewControllerBDelegate <NSObject> - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item; @end
next still in the ViewControllerB.h
you need to setup a delegate
property and synthesize in ViewControllerB.m
(接下来仍然在ViewControllerB.h
您需要设置一个delegate
属性并在ViewControllerB.m
合成)
@property (nonatomic, weak) id <ViewControllerBDelegate> delegate;
In ViewControllerB
we call a message on the delegate
when we pop the view controller.
(在ViewControllerB
,当我们弹出视图控制器时,我们在delegate
上调用一条消息。)
NSString *itemToPassBack = @"Pass this value back to ViewControllerA"; [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
That's it for ViewControllerB
.
(这就是ViewControllerB
。)
Now in ViewControllerA.h
, tell ViewControllerA
to import ViewControllerB
and conform to its protocol. (现在在ViewControllerA.h
,告诉ViewControllerA
导入ViewControllerB
并遵守其协议。)
#import "ViewControllerB.h" @interface ViewControllerA : UIViewController <ViewControllerBDelegate>
In ViewControllerA.m
implement the following method from our protocol
(在ViewControllerA.m
,从我们的协议中实现以下方法)
- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item { NSLog(@"This was returned from ViewControllerB %@",item); }
Before pushing viewControllerB
to navigation stack we need to tell ViewControllerB
that ViewControllerA
is its delegate, otherwise we will get an error.
(在将viewControllerB
推到导航堆栈之前,我们需要告诉ViewControllerB
ViewControllerA
是它的委托,否则我们将得到一个错误。)
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
(《 View Controller编程指南》中的使用委派与其他View Controller通信)
- Delegate Pattern
(代表图案)
NSNotification center It's another way to pass data.
(NSNotification中心这是传递数据的另一种方法。)
// add observer in controller(s) where you want to receive data
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeepLinking:) name:@"ha