将数据传回

我有两个视图控制器,FirstViewController第二视图控制器。我使用这段代码切换到我的第二个 ViewController (我还向它传递了一个字符串) :

secondViewController *second = [[secondViewController alloc] initWithNibName:nil bundle:nil];


second.myString = @"This text is passed from firstViewController!";


second.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;


[self presentModalViewController:second animated:YES];


[second release];

然后,我在 second ViewController 中使用这段代码切换回 firstViewController:

[self dismissModalViewControllerAnimated:YES];

这一切都很好。我的问题是,如何将数据传递给第一个 ViewController?我想要从 second ViewController 向 first ViewController 传递一个不同的字符串。

34436 次浏览

在第二个视图控制器中定义委托协议,并将第一个视图控制器设置为第二个视图控制器的委托。

找到通知中心,在通知中传回信息。这里是苹果的尝试 除非有人有其他建议,否则我会亲自处理这件事

您需要使用委托协议... ... 以下是如何做到这一点:

在第二个 ViewController 的头文件中声明一个协议:

#import <UIKit/UIKit.h>


@protocol SecondDelegate <NSObject>
-(void)secondViewControllerDismissed:(NSString *)stringForFirst
@end




@interface SecondViewController : UIViewController
{
id myDelegate;
}


@property (nonatomic, assign) id<SecondDelegate>    myDelegate;

不要忘记合成您的实现(Second ViewController.m)文件中的 my氏委托:

@synthesize myDelegate;

在 FirstViewController 的头文件中,通过以下方法订阅 Second Committee 协议:

#import "SecondViewController.h"


@interface FirstViewController:UIViewController <SecondDelegate>

现在,当您在 FirstViewController 中实例化 SecondViewController 时,您应该执行以下操作:

// If you're using a view controller built with Interface Builder.
SecondViewController *second = [[SecondViewController alloc] initWithNibName:"SecondViewController" bundle:[NSBundle mainBundle]];
// If you're using a view controller built programmatically.
SecondViewController *second = [SecondViewController new]; // Convenience initializer that uses alloc] init]
second.myString = @"This text is passed from firstViewController!";
second.myDelegate = self;
second.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:second animated:YES];
[second release];

最后,在第一个视图控制器(FirstViewController.m)的实现文件中,实现了第二个 ViewControllerDismissed 的 Second Committee 方法:

- (void)secondViewControllerDismissed:(NSString *)stringForFirst
{
NSString *thisIsTheDesiredString = stringForFirst; //And there you have it.....
}

现在,当您要关闭第二个视图控制器时,您需要调用在第一个视图控制器中实现的方法。这部分很简单。您所要做的就是在第二个视图控制器中,在解散代码之前添加一些代码:

if([self.myDelegate respondsToSelector:@selector(secondViewControllerDismissed:)])
{
[self.myDelegate secondViewControllerDismissed:@"THIS IS THE STRING TO SEND!!!"];
}
[self dismissModalViewControllerAnimated:YES];

委托协议非常,非常,非常有用。熟悉它们会对你有好处:)

NSNotification 是另一种方法,但作为一种最佳实践,我更喜欢在需要跨多个 viewController 或对象进行通信时使用它。如果您对使用 NSNotification 感到好奇,这里是我之前发布的一个答案: 从 appcommittee 中的一个线程跨多个 viewcontroller 触发事件

编辑:

如果要传递多个参数,则解除之前的代码如下所示:

if([self.myDelegate respondsToSelector:@selector(secondViewControllerDismissed:argument2:argument3:)])
{
[self.myDelegate secondViewControllerDismissed:@"THIS IS THE STRING TO SEND!!!" argument2:someObject argument3:anotherObject];
}
[self dismissModalViewControllerAnimated:YES];

这意味着在 firstViewController 内部的 Second Committee 方法实现现在看起来像:

- (void) secondViewControllerDismissed:(NSString*)stringForFirst argument2:(NSObject*)inObject1 argument3:(NSObject*)inObject2
{
NSString thisIsTheDesiredString = stringForFirst;
NSObject desiredObject1 = inObject1;
//....and so on
}

这里我可能有点不合时宜,但我开始更喜欢块语法,而不是非常冗长的委托/协议方法。如果从 vc1创建 vc2,那么在 vc2上有一个可以从 vc1设置的属性,它是一个块!

@property (nonatomic, copy) void (^somethingHappenedInVC2)(NSString *response);

然后,当在 vc2中发生了您想要告诉 vc1的事情时,只需执行您在 vc1中定义的代码块!

self.somethingHappenedInVC2(@"Hello!");

这允许您将数据从 vc2发送回 vc1。就像魔法一样。我的天,这比协议简单/干净多了。块是可怕的,需要尽可能多地拥抱。

EDIT-改进的示例

假设我们有一个 mainVC,我们希望在它上面临时显示一个 modalVC,以便从用户那里获得一些输入。为了在 mainVC 中显示 modalVC,我们需要在 mainVC 中分配/初始化它。很基本的东西。当我们创建这个 modalVC 对象时,我们还可以在它上面设置一个 block 属性,这样我们就可以轻松地在两个 vc 对象之间进行通信。因此,让我们以上面的示例为例,将以下属性放入。ModalVC 的 h 文件:

 @property (nonatomic, copy) void (^somethingHappenedInModalVC)(NSString *response);

然后,在 mainVC 中,在我们分配/初始化一个新的 modalVC 对象之后,设置 modalVC 的 block 属性如下:

ModalVC *modalVC = [[ModalVC alloc] init];
modalVC.somethingHappenedInModalVC = ^(NSString *response) {
NSLog(@"Something was selected in the modalVC, and this is what it was:%@", response);
}

所以我们只需要设置 block 属性,并定义执行该块时会发生什么。

最后,在 modalVC 中,我们可以有一个 tableViewController,它由字符串的 dataSource 数组支持。一旦选择了一行,我们可以这样做:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *selectedString = self.dataSource[indexPath.row];
self.somethingHappenedInModalVC(selectedString);
}

当然,每次我们在 modalVC 中选择一行,我们都会从 mainVC 中的 NSLog 行获得一个控制台输出。希望能帮上忙!