在视图控制器之间传递数据 [英] Passing Data between View Controllers

查看:140
本文介绍了在视图控制器之间传递数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是iOS和Objective-C以及整个MVC范例的新手,我坚持以下内容:



我有一个视图,作为一个数据输入表单,我想让用户选择多个产品。产品在另一个视图中列出,带有 UITableViewController ,我启用了多项选择。



我的问题是,如何将数据从一个视图传输到另一个视图?我将在数组中的 UITableView 上保留选择,但是如何将其传递回上一个数据输入表单视图,以便它可以与另一个一起保存提交表格时数据到核心数据?



我已经四处浏览并看到有人在应用代表中声明了一个数组。我读了一些关于Singletons的内容,但不明白这些是什么,我读了一些关于创建数据模型的内容。



执行此操作的正确方法是什么?我去了吗?

解决方案

这个问题似乎在stackoverflow上非常受欢迎,所以我想我会尝试给出一个更好的回答帮助像我这样的iOS世界中的人们。



我希望这个答案足够清楚,让人们理解并且我没有错过任何东西。



传递数据



将数据从另一个视图控制器传递到视图控制器。如果要将对象/值从一个视图控制器传递到另一个可能正在推送到导航堆栈的视图控制器,则可以使用此方法。



为此例如,我们将 ViewControllerA ViewControllerB



要通过一个 BOOL ViewControllerA ViewControllerB 我们会做的在 ViewControllerB.h 为<创建属性code> BOOL

  @property(nonatomic,assign)BOOL isSomethingEnabled; 


  • ViewControllerA 中你需要告诉它 ViewControllerB 所以使用

      #importViewControllerB.h 

    然后你要加载视图的地方,例如。 didSelectRowAtIndex 或某些 IBAction 您需要在 ViewControllerB 然后将其推送到导航堆栈。

      ViewControllerB * viewControllerB = [[ViewControllerB alloc] initWithNib:@ViewControllerB包:零]; 
    viewControllerB.isSomethingEnabled = YES;
    [self pushViewController:viewControllerB animated:YES];

    这将在<$ c中设置 isSomethingEnabled $ c> ViewControllerB BOOL


  • 使用Segues传递数据



    如果您正在使用您最有可能使用segues的故事板,并且需要此过程来传递数据。这与上面的类似,但不是在推动视图控制器之前传递数据,而是使用名为

    的方法

       - ( void)prepareForSegue:(UIStoryboardSegue *)segue发送者:(id)发件人

    所以传递 BOOL ViewControllerA ViewControllerB 我们将执行以下操作:


    1. ViewControllerB.h BOOL

        @property(nonatomic,assign)BOOL isSomethingEnabled; 


    2. ViewControllerA 中你需要告诉它 ViewControllerB 所以使用

        #importViewControllerB.h 


    3. ViewControllerA ViewControllerB 并给它一个标识符,在这个例子中我们称之为showDetailSegue


    4. 接下来我们需要将方法添加到执行任何segue时调用的 ViewControllerA ,因为我们需要检测哪个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 in ViewControllerB to BOOL value YES


    传递数据



    要将数据从 ViewControllerB 传递回 ViewControllerA ,您需要使用协议和代理 Blocks ,后者可以用作松散耦合的回调机制。



    要做到这一点,我们将使 ViewControllerA ViewControllerB 的委托。这允许 ViewControllerB 将消息发送回 ViewControllerA ,使我们能够发回数据。



    对于 ViewControllerA 作为 ViewControllerB 的委托,它必须符合 ViewControllerB 我们必须指定的协议。这告诉 ViewControllerA 它必须实现哪些方法。


    1. In ViewControllerB.h ,低于 #import ,但高于 @interface 你指定协议。

        @class ViewControllerB; 

      @protocol ViewControllerBDelegate< NSObject>
      - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
      @end


    2. 下一步仍在 ViewControllerB中。 h 您需要设置委托属性并在中合成ViewControllerB.m

        @property(非原子,弱)id< ViewControllerBDelegate>代表; 


    3. ViewControllerB 中我们称之为当我们弹出视图控制器时,委托上的消息。

        NSString * itemToPassBack = @将此值传递回ViewControllerA; 
      [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];


    4. 这是 ViewControllerB 。现在在 ViewControllerA.h 中,告诉 ViewControllerA 导入 ViewControllerB 并符合其协议。

        #importViewControllerB.h

      @interface ViewControllerA:UIViewController < ViewControllerBDelegate>


    5. ViewControllerA.m 中实施我们的协议中的以下方法

         - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item 
      {
      NSLog(@这是从ViewControllerB%@返回的,项目);
      }


    6. 在推送 viewControllerB 到导航堆栈我们需要告诉 ViewControllerB ViewControllerA 是它的委托,否则我们会收到错误。

        ViewControllerB * viewControllerB = [[ViewControllerB alloc] initWithNib:@ViewControllerBbundle:nil]; 
      viewControllerB.delegate = self
      [[self navigationController] pushViewController:viewControllerB animated:YES];







    < h3>参考文献


    I'm new to iOS and Objective-C and the whole MVC paradigm and I'm stuck with the following:

    I have a view that acts as a data entry form and I want to give the user the option to select multiple products. The products are listed on another view with a UITableViewController and I have enabled multiple selections.

    My question is, how do I transfer the data from one view to another? I will be holding the selections on the UITableView in an array, but how do I then pass that back to the previous data entry form view so it can be saved along with the other data to Core Data on submission of the form?

    I have surfed around and seen some people declare an array in the app delegate. I read something about Singletons but don't understand what these are and I read something about creating a data model.

    What would be the correct way of performing this and how would I go about it?

    解决方案

    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, assign) 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, assign) 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 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.

    1. 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
      

    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"
      
      @interface ViewControllerA : 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

    这篇关于在视图控制器之间传递数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆