使用Segue在View Controllers之间传递数据 [英] Passing data between View Controllers using Segue

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

问题描述

我是iOS新手。我在ViewControllers之间传递数据时遇到问题。
我有三个viewControllers(view_1,view_2和view_3)。

I am new to iOS. I am facing a problem passing the data between ViewControllers. I have three viewControllers (view_1 ,view_2 and view_3).

我的设置: -


  • 选择view_1

  • 推送view_2

  • 推送view_3

我想发送ViewController参考(id)'view_1'到'view_3'。所以我在'view_1'中包含包含view_3并将值设置为'view_3'变量(使用 view_3 * v3 = [[view_3] alloc] init]; v3.reference = self; )。在控制台中显示:

I want to send the ViewController reference(id) of 'view_1' to 'view_3'. so i include include "view_3" in 'view_1' and set the value into the variable of 'view_3'( using view_3 *v3=[[view_3 alloc] init ]; v3.reference=self;). In the console it shows:


查看控制器: - ; < ViewController:0x89e9540>

view controller :- ; <ViewController: 0x89e9540>

在'view_1'但在'view_3'中,在控制台中显示

in the 'view_1' but in the 'view_3', in console it shows


查看控制器(null)

view controller (null)

但当我用'时view_2'用于传递此数据的工作。但是怎么样?我想知道这种行为,是否有任何解决方案来创建这个?

But when i used 'view_2' for passing this data its work. But how? I want to know this behaviour, And Is there any solution to creating this?

请帮忙。

推荐答案

当触发segue时将数据传递到目标控制器将通过重写方法来实现prepareForSegue:sender:

"Passing data to the destination Controller" when a segue is triggered will be achieved by overriding method prepareForSegue:sender:.

通常,您将数据而不是源视图控制器传递到目标视图控制器。 数据可能是您的应用程序模型的某个方面。它是像User这样的对象,或者可能是包含User等的数组。

Generally, you pass data and NOT the source view controller, to the destination view controller. "data" may be a certain aspect of your application "model". It's an object like "User", or perhaps an array containing "User", etc.

目的地视图控制器了解 source 视图控制器。这意味着,目标视图控制器不需要导入源视图控制器的标头。

The destination view controller shall not have any knowledge of the source view controller. That means, the destination view controller does not need to import the header of the source view controller.

另一方面,视图controller 可能知道目的地视图控制器的具体类或目标视图控制器的 base 类,因此将导入标题目标视图控制器。

On the other hand, the source view controller may have knowledge of the concrete class of the destination view controller or a base class of the destination view controller, and thus will import the header of the destination view controller.

请参阅:触发Segue时配置目标控制器

如果需要某种排序在源和目标之间的通信协议,您可以使用委派与其他视图控制器进行通信。这涉及@protocol的定义(例如,具有方法 doneButton )和属性委托,其定义在目标视图控制器。如果目标视图控制器的特定到目标视图控制器,则应在目标视图控制器的标头中定义该协议。通常,您从目标控制器的角度定义协议,而不是源控制器的要求。

If you need some sort of "communication protocol" between the source and the destination, you might employ Delegation to communicate with other view controllers. This involves the definition of a @protocol (e.g. having a method doneButton) and a property delegate which is defined in the destination view controller. The protocol should be defined in the header of the destination view controller, if it's specific to the destination view controller. Usually, you define tho protocol from the view point of the destination controller, and not from the requirements of the source controller.

源视图控制器然后创建一个委托(除非,它本身已经是)并设置目标视图控制器的委托。目标视图控制器将委托方法发送给委托,委托处理它。

The source view controller then creates a delegate (unless, it itself is it already) and sets the delegate of of the destination view controller. The destination view controller will send the delegate methods to the delegate, and the delegate handles it.

现在,将数据从VC_A传递到VC_B应该是直接的。您应该阅读一些使用 prepareForSegue:sender:的示例。例如,目标视图控制器可能具有属性 data ,表示应显示的 thing 。源视图控制器必须在 prepareForSegue:sender:中设置此属性。

Now, passing "data" from a VC_A to VC_B should be straight forward. You should read a few examples which use prepareForSegue:sender:. For example, the destination view controller may have a property data which represents the thing it should display. The source view controller must set this property in prepareForSegue:sender:.

通过VC_B将数据从VC_A传递到VC_C也应该是直截了当的。

Passing data from VC_A over VC_B to VC_C should be straight forward as well.

注意:每个视图控制器可以定制(分离,修改,准备,切片,转换等) > data 使下一个视图控制器成为合适的数据

Note: Each view controller may tailor (separate, modify, prepare, slice, transform, etc.) its data to make it a suitable data for the next view controller.

如果VC_C需要其源视图控制器VC_B中没有的数据,那么有几种方法可以解决这个问题。但是,这通常是糟糕设计的标志

If VC_C needs data that is not available in its source view controller VC_B, then there are a couple of approaches to solve this. However, this is usually a sign of bad design.

可以拥有一个应用程序模型,它是全球。假设,您的应用程序模型是 Document 类型的对象。假设,在任何时候只有该应用程序模型的一个实例。然后,该模型是一个单身人士,可以从您的应用程序中的任何位置访问,如下所示:

You could have an application model, which is global. Suppose, your "application model" is an object of type Document. Suppose, at any time there is only one instance of that application model. Then, the model is a "Singleton", which could be accessed from anywhere in your app like so:

Document* document = [Document sharedDocument];

但是,获取模型实例的首选方法是第一次查看需要访问它的控制器,在这种情况下:VC_A。

However, the preferred way to get an instance of a model is in the first view controller which requires access to it, in this case: VC_A.

然后,VC_A传递文档实例到下一个视图控制器VC_B。 VC_B将文档对象传递给VC_C。

Then, VC_A passes a Document instance to the next view controller VC_B. And VC_B passes the document object to VC_C.

您应该阅读官方文档适用于iOS的View Controller编程指南

假设您有一个用户列表。该列表应显示在表视图控制器中,并且还应该有一个详细视图,显示一个用户的详细信息。

Suppose, you have a list "Users". The list should be displayed in a table view controller, and there should also be a detail view, showing details of one User.

表视图控制器将具有数据 property users

The table view controller will have a "data" property users:

UsersTableViewController.h

@interface UsersTableViewController : UIViewController
@property (nonatomic, readonly) NSArray* users;
@end

(严格来说,这个用户属性不需要是公共的。例如,如果表视图在内部获取用户自己的列表,则无需从外部访问它。

(Strictly, this user property doesn't need to be public. For example, if the table view internally obtains the list of users itself, there is not need to access it from outside.

users数组是表视图的 data ,它应以行显示。每行显示用户的摘要。

The "users" array is the data of the table view which shall be displayed in rows. Each row shows a "summary" of a user.

用户的更多详细信息应显示在详细视图控制器中。详细视图控制器的数据是用户类型的单个用户。

More details of a user should be displayed in a detail view controller. The detail view controller's data is a single user of type User.

当用户在表格视图中选中某一行时,将显示详细视图控制器。在显示之前,表格视图控制器必须配置详细信息视图控制器:表视图控制器为当前选定的用户分配详细视图控制器的数据属性。因此,详细视图控制器应具有 public 属性用户

When the user tabs a certain row in the table view, the detail view controller will be displayed. Before it will be displayed, the table view controller must configure the detail view controller: the table view controller assigns the detail view controller's "data property" the current selected user. Thus, the detail view controller should have a public property user:

@interface UserViewController : UIViewController
@property (nonatomic) User* user;
@end

表视图控制器在 prepareForSegue:发件人::

UsersTableViewController.m

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"ShowUserDetails"]) {
        UserViewController* userViewController = [segue destinationViewController];
        userViewController.user = [self.users objectInListAtIndex:[self.tableView indexPathForSelectedRow].row];
    }
}






示例2



第二个示例更复杂,并使用委派作为在控制器之间建立通信的方法。


Example 2

The second example is more complex and uses "Delegation" as a means to establish a communication between controllers.

警告:


这不是一个完整的例子。本示例的目的是演示如何使用委派。如示例所示,数据任务的全功能实现将需要更多的努力。在这种情况下,委托将是实现这一目标的最佳方法(恕我直言)。

This is not a complete example. The purpose of this example shall demonstrate how to use "Delegation". A full featured implementation of data tasks as shown in the example will require significant more effort. In this scenarios like these, "Delegation" will be the most preferred approach to accomplish this (IMHO).

假设我们想要


  • 显示用户

  • 修改(编辑)用户

  • 在详细信息视图中创建新用户,

  • 删除用户

  • Show a User
  • Modify (edit) a User
  • Create New a User, and
  • Delete a User

这些数据任务不应由详细视图控制器本身执行,而委托是负责这些数据任务。

These "data tasks" shall not be performed by the detail view controller itself, instead a delegate is responsible for these data tasks.

这些数据操作应由代表处理:

These data actions shall be handled by the delegate:

@protocol UserDataSourceDelegateProtocol <NSObject>
- (User*) viewControllerUser:(UserViewControllerBase*)viewController;
- (void) viewController:(UserViewControllerBase*)viewController dismissWithUpdatedUser:(User*)user;
- (void) viewController:(UserViewControllerBase*)viewController dismissWithDeletedUser:(User*)user;
- (void) viewController:(UserViewControllerBase*)viewController dismissWithCreatedUser:(User*)user;
@end

此协议反映了基本的CRUD方法(创建,读取,更新,删除) )。

This protocol reflects the basic CRUD methods (Create, Read, Update, Delete).

同样,我们不希望细节视图控制器本身执行这些数据方法,但是这将由一个实现 UserDataSourceDelegateProtocol 的实例。详细视图控制器具有此委托的属性,并将这些数据任务发送给委托。

Again, we don't want the Detail View Controller itself to perform these data methods, but instead this will be performed by an instance implementing the UserDataSourceDelegateProtocol. The detail view controller has a property of this delegate, and it sends these "data tasks" to the delegate.

可能有几个详细视图控制器,所有抽象子类class UserViewControllerBase ,用于处理 show 编辑创建任务。可以在表格视图和显示用户视图控制器中执行用户删除:

There may be several detail view controllers, all subclasses of abstract class UserViewControllerBase which handle the show, edit and create tasks. Deletion of a user can be performed in the table view and in the "Show User" view controller:


  • ShowUserViewController

  • EditUserViewController

  • NewUserViewController

  • ShowUserViewController
  • EditUserViewController
  • NewUserViewController

例如 EditUserViewController 将发送 viewController:dismissWithUpdatedUser:当用户选中后退按钮并且用户已修改用户对象时。现在,代表可能允许也可能不允许关闭详细视图。例如,当存在验证错误时,它可能会禁止它。

For example The EditUserViewController will send viewController:dismissWithUpdatedUser: when the user tabs the "back" button AND if the user has modified the user object. Now, the delegate may or may not allow to dismiss the detail view. It may disallow it when there are validation errors for example.

UserDataSourceDelegateProtocol 协议可能可以在根视图控制器中实现,例如表视图控制器。但是,一个单独的类,其唯一的责任是处理数据任务可能更合适。在下面的示例中,表视图控制器也将是此数据处理程序。

The UserDataSourceDelegateProtocol protocol may be implemented in the root view controller, the table view controller for example. However, a separate class whose sole responsibility is to handle data tasks may be more appropriate. In the sample below, the table view controller will also be this data handler.

UserDataSourceDelegateProtocol 可以在一个额外的标题。

The UserDataSourceDelegateProtocol may be defined in an extra header.

UsersTableViewController.m

#import "UserDataSourceDelegateProtocol.h"
#import "ShowUserViewController.h"


@interface UsersTableViewController () <UserDataSourceDelegateProtocol> 
@property (nonatomic, readonly) NSArray* users;
@end


// This delegate will be called when the detail view controller request 
// the user object which shall be displayed.
- (User*) viewControllerUser:(UserViewControllerBase*)viewController {
    return [self.users objectInListAtIndex:[self.tableView indexPathForSelectedRow].row];
}

此处,表视图控制器配置显示用户详细信息视图控制器:

Here, the Table View Controller configures the Show User Detail View Controller:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:UserShowSegueID])
    {
        ShowUserViewController* showViewController = segue.destinationViewController;
        showViewController.delegate = self; // Data Source Handler is self
    }
}

编辑用户视图控制器通常是显示用户视图控制器的目标视图控制器,当用户选中编辑按钮时,它将被查看。

The "Edit User" view controller is usually a destination view controller of the "Show User" view controller, which gets viewed when the user tabs the "Edit" button.

显示用户 视图控制器将为
设置委托编辑用户视图控制器获取相同的委托:

The "Show User" view controller will setup the delegate for the "Edit User" view controller gets the same delegate:

ShowUserViewController.m

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:UserEditSegueID])
    {
        EditUserViewController* editViewController = segue.destinationViewController;
        editViewController.delegate = self.delegate; // pass through the data source hanlder
    }
}

数据委托可以按如下方式处理更新的用户:

The data delegate may handle an updated user as follows:

UsersTableViewController.m

- (void) viewController:(UserViewControllerBase*)viewController
 dismissWithUpdatedUser:(User*)user {
    if (/* is valid user and can be saved */) {
        [viewController.presentingViewController dismissViewControllerAnimated:YES
                                                                     completion:nil];
    }
}

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

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