这个问题在stackoverflow上似乎很受欢迎,所以我想我会尝试给出一个更好的答案来帮助像我这样的iOS初学者。
我希望这个答案足够清晰,让人们理解,并且我没有错过任何东西。
转发数据
将数据从另一个视图控制器传递到视图控制器。如果要将对象/值从一个视图控制器传递到可能要推送到导航堆栈的另一个视图控制器,则可以使用此方法。
在这个例子中,我们将
ViewControllerA和
ViewControllerB
要将
BOOL值从传递
ViewControllerA给
ViewControllerB我们,请执行以下操作。
在
ViewControllerB.h
为BOOL
@property (nonatomic, assign) BOOL isSomethingEnabled;
在
ViewControllerA
你需要告诉它,ViewControllerB
所以使用#import "ViewControllerB.h"
然后在您想加载视图的位置。
didSelectRowAtIndex或一些
IBAction您需要设置的属性,
ViewControllerB然后再将其推入导航堆栈。
ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];viewControllerB.isSomethingEnabled = YES;[self pushViewController:viewControllerB animated:YES];
这将设置
isSomethingEnabled在
ViewControllerB以
BOOL价值
YES。
使用Segues转发数据
如果使用情节提要,则很有可能使用segues,并且需要此过程将数据转发。这与上面的类似,但是不是在推送视图控制器之前传递数据,而是使用一种称为
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
因此,要将
BOOLfrom 传递
ViewControllerA给
ViewControllerB我们,请执行以下操作:
在
ViewControllerB.h
为BOOL
@property (nonatomic, assign) BOOL isSomethingEnabled;
在
ViewControllerA
你需要告诉它,ViewControllerB
所以使用#import "ViewControllerB.h"
从创建的SEGUE
ViewControllerA
到ViewControllerB
的故事板,并给它一个标识符,在这个例子中,我们叫它"showDetailSegue"
接下来,我们需要在
ViewControllerA
执行任何segue时将方法添加到被调用的方法,因此,我们需要检测调用了哪个segue并执行某些操作。在我们的示例中,我们将检查"showDetailSegue"
是否执行了此操作,然后将我们的BOOL
值传递给ViewControllerB
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{if([segue.identifier isEqualToString:@"showDetailSegue"]){ ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController; controller.isSomethingEnabled = YES;}}
如果您将视图嵌入导航控制器中,则需要将上面的方法稍微更改为以下方法
-(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; }}这将设置
isSomethingEnabled在
ViewControllerB以
BOOL价值
YES。
传回数据
要将数据传递回
ViewControllerB给
ViewControllerA您,您需要使用 Protocols and Delegates 或
Blocks ,后者可以用作回调的松散耦合机制。
为此,我们将
ViewControllerA委托
ViewControllerB。这样可以
ViewControllerB将信息发送回去,
ViewControllerA使我们能够将数据发送回去。
对于
ViewControllerA成为一个代表
ViewControllerB它必须符合
ViewControllerB我们有指定的协议。这告诉
ViewControllerA它必须实现哪些方法。
在
ViewControllerB.h
中的#import
,但在上方@interface
指定协议。@class ViewControllerB;
@protocol ViewControllerBDelegate
- (void)addItemViewController:(ViewControllerB )controller didFinishEnteringItem:(NSString )item;
@end接下来仍然
ViewControllerB.h
需要设置delegate
属性并在ViewControllerB.m
@property (nonatomic, weak) id <ViewControllerBDelegate> delegate;
在
ViewControllerB
我们delegate
弹出视图控制器时,我们会调用一条消息。NSString *itemToPassBack = @"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
就是这样
ViewControllerB
。现在,中ViewControllerA.h
,告诉ViewControllerA
导入ViewControllerB
并遵守其协议。#import "ViewControllerB.h"
@interface ViewControllerA : UIViewController
在
ViewControllerA.m
落实从我们的协议下面的方法- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(@”This was returned from ViewControllerB %@”,item);
}在推
viewControllerB
送到导航堆栈之前,我们需要告诉ViewControllerB
它ViewControllerA
是它的委托,否则我们将得到一个错误。ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
viewControllerB.delegate = self
[[self navigationController] pushViewController:viewControllerB animated:YES];
参考资料
- 《 View Controller编程指南》 中的使用委派与其他View Controller通信 __
- 代表图案
NSNotification中心 这是传递数据的另一种方法。
// add observer in controller(s) where you want to receive data[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeeplinking:) name:@"handleDeeplinking" object:nil];-(void) handleDeeplinking:(NSNotification *) notification { id someObject = notification.object // some custom object that was passed with notification fire.}// post notificationid someObject;[NSNotificationCenter.defaultCenter postNotificationName:@"handleDeeplinking" object:someObject];将数据从一个类传递回另一个类 (一个类可以是任何控制器,网络/会话管理器,UIView子类或任何其他类)
块是匿名函数。
本示例将数据从 控制器B 传递到 控制器A
定义一个块
@property void(^selectedVoucherBlock)(NSString *); // in ContollerA.h
*在需要值的地方 *添加块处理程序(侦听器) (例如,您需要在ControllerA中的API响应或在A上需要ContorllerB数据)
// in ContollerA.m- (void)viewDidLoad { [super viewDidLoad]; __unsafe_unretained typeof(self) weakSelf = self; self.selectedVoucherBlock = ^(NSString *voucher) { weakSelf->someLabel.text = voucher; };}转到控制器B
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];ControllerB *vc = [storyboard instantiateViewControllerWithIdentifier:@"ControllerB"];vc.sourceVC = self; [self.navigationController pushViewController:vc animated:NO];
火块
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath { NSString *voucher = vouchersArray[indexPath.row]; if (sourceVC.selectVoucherBlock) { sourceVC.selectVoucherBlock(voucher); } [self.navigationController popToViewController:sourceVC animated:YES];}块的另一个工作示例



