`

(转)[ios]页面跳转传值参考

    博客分类:
  • IOS
阅读更多

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.

  1. in ViewControllerB.h create a property for the BOOL

    @property(nonatomic) BOOL *isSomethingEnabled;
  2. 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:

  1. in ViewControllerB.h create a property for the BOOL

    @property(nonatomic) BOOL *isSomethingEnabled;
  2. in ViewControllerA you need to tell it about ViewControllerB so use an

    #import "ViewControllerB.h"
  3. Create a the segue from ViewControllerA to ViewControllerB on the storyboard and give it an identifier, in this example we'll call it "showDetailSegue"

  4. 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 BOOLvalue 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.

  1. In ViewControllerB.h, below the #import, but above @interface you specify the protocol.

    @classViewControllerB;@protocolViewControllerBDelegate<NSObject>-(void)addItemViewController:(ViewControllerB*)controller didFinishEnteringItem:(NSString*)item;@end
  2. next still in the ViewControllerB.h you need to setup a delegate property and synthesize in ViewControllerB.m

    @property(nonatomic, weak) id <ViewControllerBDelegate>delegate;
  3. 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];
  4. 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>
  5. In ViewControllerA.m implement the following method from our protocol

    -(void)addItemViewController:(ViewControllerB*)controller didFinishEnteringItem:(NSString*)item
    {NSLog(@"This was returned from ViewControllerB %@",item);}
  6. 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页面跳转传值

    本文将详细讲解“ios页面跳转传值”这一主题,以及如何使用`delegate`来隐藏键盘。 首先,让我们理解页面跳转的概念。在iOS应用中,我们通常使用`UIStoryboardSegue`或`UINavigationController`进行页面之间的切换...

    IOS界面跳转传值

    详细的IOS界面跳转及传值,包含toolbar实现多个view之间的跳转以及界面内按钮实现跳转,用到单例模式: 在第一个界面登陆,在第二个界面显示名字,并且根据不同的名字显示不同的图片 (最好不要加toolbar) 博客参考...

    IOS页面传值

    标题"iOS页面传值"涵盖了三种常见的数据传递方法:单例传值、委托(Delegate)传值以及属性(Property)传值。下面将详细阐述这三种方式。 **1. 单例传值** 单例模式是一种设计模式,它保证一个类只有一个实例,并...

    IOS开发页面传值

    本教程将详细讲解四种常见的iOS页面传值方法:属性(Property)、代理(Delegate)、Block以及通知(Notification)。通过提供的四个项目,我们将逐一剖析这些方法的使用场景和实现步骤。 1. **属性传值(1.属性...

    iOS页面跳转动画

    iOS页面跳转的各式动画,比较全面; UIView animateWithDuration:DURATION animations:^{ [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationTransition:transition forView:view ...

    页面间跳转和传值

    在iOS开发中,页面间跳转和传值是应用程序中不可或缺的部分,它们使得用户能够流畅地在各个界面之间切换,并且在切换过程中传递数据。在这个主题中,我们将深入探讨如何在Objective-C或Swift中实现这两种功能,以...

    ios 最全传值方式

    在iOS开发中,传值是应用之间或组件之间通信的关键技术。本文将深入探讨iOS中最常用的几种传值方式,包括Block、Delegate、属性赋值、代理协议以及Notification Center。了解并熟练掌握这些方法,能够帮助开发者更加...

    ios页面跳转

    在iOS应用开发中,页面跳转是用户交互的重要组成部分,它涉及到用户界面的导航和流程控制。本示例主要探讨了三种iOS页面跳转的方法:通过Storyboard进行导航、使用NavigationController以及视图转换(ViewTransition...

    ios 使用代理双向传值

    标题提到的"ios 使用代理双向传值"是指在Objective-C或Swift中利用代理协议(Delegate Protocol)进行数据的双向传递,通常在不同界面之间或者组件之间进行通信时使用。这种设计模式允许一个对象(发送者)通知另一...

    iOS俩个app传值

    在iOS开发中,当涉及到两个不同的应用程序之间进行数据交换或用户流程跳转时,我们通常会用到App间通信(Inter-App Communication)的技术。这个过程涵盖了多种方法,包括URL Scheme、Universal Links、Pasteboard、...

    iOS 实现页面跳转

    在iOS开发中,页面跳转是应用程序中不可或缺的一部分,它允许用户在不同的视图和控制器之间导航。本教程将深入探讨如何在iOS中实现页面跳转,特别关注新手开发者的需求。我们将讨论两种主要的页面跳转方式:模态...

    ios 委托代理传值demo

    在标题“ios 委托代理传值demo”中,我们关注的是如何使用委托代理进行值传递。以下是实现这个功能的步骤: 1. **定义协议**:首先,我们需要创建一个协议,这个协议会包含那些用于传递值的方法。例如,可以定义一...

    iOS Notification正向传值

    "iOS Notification正向传值"指的是通过苹果的Notification Center服务实现从一个对象(发送者)向另一个对象(接收者)传递数据的方式。这种方法不同于传统的代理、KVO(Key-Value Observing)或者Block,它更适用于...

    ios-Swift ----- tabar ,tableview,collection,页面间传值.zip

    在这个"ios-Swift ----- tabar,tableview,collection,页面间传值.zip"的压缩包中,我们可以看到开发者分享了如何使用Swift来实现四个关键组件:Tab Bar、Table View、Collection View以及页面间的值传递。...

    iOS 代理传值简单demo

    在这个“iOS 代理传值简单demo”中,我们将探讨如何使用代理协议(Delegate Protocol)来实现界面间的数据传递,这对于初学者理解Objective-C或Swift中的代理机制非常有帮助。 首先,让我们了解代理的基本概念。...

    swift-iOS五种传值方法

    iOS五种传值方法

    iOS Block 界面传值

    总结,Block在iOS开发中提供了强大的代码复用和灵活性,使得在界面传值和处理事件响应时更加便捷高效。了解和熟练掌握Block的使用,能显著提升开发效率,优化代码结构,为iOS应用开发带来诸多便利。在实际项目中,...

    ios-block逆传值页面间的.zip

    在这个名为"ios-block逆传值页面间的.zip"的资源中,我们主要关注的是如何使用Block来实现页面间的反向传值。Block是Objective-C和Swift中的一种强大的特性,它可以作为参数传递,也可以作为返回值。对于初学者来说...

    iOS委托反向传值

    这种机制在iOS开发中尤其常见,比如在表单填写后返回上一页面时更新显示的数据。 首先,我们需要理解什么是委托。在Objective-C和Swift中,委托是一种设计模式,用于让一个对象通知另一个对象当某个事件发生时。这...

Global site tag (gtag.js) - Google Analytics