http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers
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 the BOOL
@property(nonatomic) BOOL *isSomethingEnabled;
-
in ViewControllerA
you need to tell it about ViewControllerB
so use an
#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.
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
.
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 the BOOL
@property(nonatomic) BOOL *isSomethingEnabled;
-
in ViewControllerA
you need to tell it about ViewControllerB
so use an
#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"
-
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 our BOOL
value to 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
.
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.
@classViewControllerB;@protocolViewControllerBDelegate<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
@property(nonatomic, weak) id <ViewControllerBDelegate>delegate;
-
In ViewControllerB
we call a message on the delegate
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 in ViewControllerA.h
, tell ViewControllerA
to import ViewControllerB
and conform to its protocol.
#import "ViewControllerB.h"@interfaceViewControllerA: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);}
-
Before pushing viewControllerB
to navigation stack we need to tell ViewControllerB
that ViewControllerA
is its delegate, otherwise we will get an error.
ViewControllerB*viewControllerB =[[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
viewControllerB.delegate= self
[[self navigationController] pushViewController:viewControllerB animated:YES];
References
Further Help
There are many answers to this questions offering many different ways to perform view controller communication that would indeed work, but I don't see anywhere mentioned which one are actually best to use and which ones to avoid.
In practice, in my opinion only a few solutions are recommended:
- To pass data forward:
- override the
prepare(for:sender:)
method of UIViewController
when using a storyboard and segues
- pass data through an initializer or through properties when performing view controller transitions thtough code
- To pass data backwards
- update the app shared state (which you can pass forward between view controllers with either one of the methods above)
- use delegation
- use an unwind segue
Solutions I recommend NOT to use:
- Referencing the previous controller directly instead of using delegation
- Sharing data through a singleton
- Passing data through the app delegate
- Sharing data through the user defaults
- Passing data through notifications
These solutions, although working in the short term, introduce too many dependencies that will garble the architecture of the app and create more problems later.
For those interested, I wrote some articles that address these points more in depth and highlight the various drawbacks:
相关推荐
本文将详细讲解“ios页面跳转传值”这一主题,以及如何使用`delegate`来隐藏键盘。 首先,让我们理解页面跳转的概念。在iOS应用中,我们通常使用`UIStoryboardSegue`或`UINavigationController`进行页面之间的切换...
详细的IOS界面跳转及传值,包含toolbar实现多个view之间的跳转以及界面内按钮实现跳转,用到单例模式: 在第一个界面登陆,在第二个界面显示名字,并且根据不同的名字显示不同的图片 (最好不要加toolbar) 博客参考...
标题"iOS页面传值"涵盖了三种常见的数据传递方法:单例传值、委托(Delegate)传值以及属性(Property)传值。下面将详细阐述这三种方式。 **1. 单例传值** 单例模式是一种设计模式,它保证一个类只有一个实例,并...
本教程将详细讲解四种常见的iOS页面传值方法:属性(Property)、代理(Delegate)、Block以及通知(Notification)。通过提供的四个项目,我们将逐一剖析这些方法的使用场景和实现步骤。 1. **属性传值(1.属性...
iOS页面跳转的各式动画,比较全面; UIView animateWithDuration:DURATION animations:^{ [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationTransition:transition forView:view ...
在iOS开发中,页面间跳转和传值是应用程序中不可或缺的部分,它们使得用户能够流畅地在各个界面之间切换,并且在切换过程中传递数据。在这个主题中,我们将深入探讨如何在Objective-C或Swift中实现这两种功能,以...
在iOS开发中,传值是应用之间或组件之间通信的关键技术。本文将深入探讨iOS中最常用的几种传值方式,包括Block、Delegate、属性赋值、代理协议以及Notification Center。了解并熟练掌握这些方法,能够帮助开发者更加...
在iOS应用开发中,页面跳转是用户交互的重要组成部分,它涉及到用户界面的导航和流程控制。本示例主要探讨了三种iOS页面跳转的方法:通过Storyboard进行导航、使用NavigationController以及视图转换(ViewTransition...
标题提到的"ios 使用代理双向传值"是指在Objective-C或Swift中利用代理协议(Delegate Protocol)进行数据的双向传递,通常在不同界面之间或者组件之间进行通信时使用。这种设计模式允许一个对象(发送者)通知另一...
在iOS开发中,当涉及到两个不同的应用程序之间进行数据交换或用户流程跳转时,我们通常会用到App间通信(Inter-App Communication)的技术。这个过程涵盖了多种方法,包括URL Scheme、Universal Links、Pasteboard、...
在iOS开发中,页面跳转是应用程序中不可或缺的一部分,它允许用户在不同的视图和控制器之间导航。本教程将深入探讨如何在iOS中实现页面跳转,特别关注新手开发者的需求。我们将讨论两种主要的页面跳转方式:模态...
在标题“ios 委托代理传值demo”中,我们关注的是如何使用委托代理进行值传递。以下是实现这个功能的步骤: 1. **定义协议**:首先,我们需要创建一个协议,这个协议会包含那些用于传递值的方法。例如,可以定义一...
"iOS Notification正向传值"指的是通过苹果的Notification Center服务实现从一个对象(发送者)向另一个对象(接收者)传递数据的方式。这种方法不同于传统的代理、KVO(Key-Value Observing)或者Block,它更适用于...
在这个"ios-Swift ----- tabar,tableview,collection,页面间传值.zip"的压缩包中,我们可以看到开发者分享了如何使用Swift来实现四个关键组件:Tab Bar、Table View、Collection View以及页面间的值传递。...
在这个“iOS 代理传值简单demo”中,我们将探讨如何使用代理协议(Delegate Protocol)来实现界面间的数据传递,这对于初学者理解Objective-C或Swift中的代理机制非常有帮助。 首先,让我们了解代理的基本概念。...
iOS五种传值方法
总结,Block在iOS开发中提供了强大的代码复用和灵活性,使得在界面传值和处理事件响应时更加便捷高效。了解和熟练掌握Block的使用,能显著提升开发效率,优化代码结构,为iOS应用开发带来诸多便利。在实际项目中,...
在这个名为"ios-block逆传值页面间的.zip"的资源中,我们主要关注的是如何使用Block来实现页面间的反向传值。Block是Objective-C和Swift中的一种强大的特性,它可以作为参数传递,也可以作为返回值。对于初学者来说...
这种机制在iOS开发中尤其常见,比如在表单填写后返回上一页面时更新显示的数据。 首先,我们需要理解什么是委托。在Objective-C和Swift中,委托是一种设计模式,用于让一个对象通知另一个对象当某个事件发生时。这...