dismissModalViewController并传回数据

时间:2011-06-01 15:34:19

标签: iphone ios uiviewcontroller modalviewcontroller

我有两个视图控制器, firstViewController secondViewController 。我正在使用此代码切换到我的secondViewController(我也传递一个字符串):

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];

然后我在secondViewController中使用此代码切换回firstViewController:

[self dismissModalViewControllerAnimated:YES];

所有这一切都很好。我的问题是,如何将数据传递给firstViewController?我想从secondViewController传递一个不同的字符串到firstViewController。

4 个答案:

答案 0 :(得分:141)

您需要使用委托协议......以下是如何执行此操作:

在secondViewController的头文件中声明一个协议。它应该是这样的:

#import <UIKit/UIKit.h>

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


@interface SecondViewController : UIViewController
{
    id myDelegate;  
}

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

不要忘记在您的实现(SecondViewController.m)文件中合成myDelegate:

@synthesize myDelegate;

在FirstViewController的头文件中,通过执行以下操作订阅SecondDelegate协议:

#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)的实现文件中,为SecondViewControllerDismissed实现SecondDelegate的方法:

- (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];

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

NSNotifications是另一种方法,但作为一种最佳实践,当我想跨多个viewControllers或对象进行通信时,我更喜欢使用它。如果您对使用NSNotifications感到好奇,这是我之前发布的答案:Firing events accross multiple viewcontrollers from a thread in the appdelegate

编辑:

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

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中的SecondDelegate方法实现现在看起来像:

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

答案 1 :(得分:40)

我可能在这里不合适,但我开始更喜欢块语法到非常详细的委托/协议方法。如果从vc1创建vc2,则在vc2上有一个属性,你可以从vc1设置一个块!

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

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

self.somethingHappenedInVC2(@"Hello!");

这允许您将数据从vc2发送回vc1。就像魔术一样。 IMO,这比协议更容易/更清洁。块很棒,需要尽可能地接受。

编辑 - 改进示例

假设我们有一个mainVC,我们想要暂时提供一个modalVC来获取用户的一些输入。为了从mainVC呈现modalVC,我们需要在mainVC中分配/ init它。很基本的东西。好吧,当我们创建这个modalVC对象时,我们还可以在其上设置一个块属性,以便我们在两个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);
}

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

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

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

当然,每次我们在modalVC中选择一行时,我们将从mainVC中获取NSLog线路的控制台输出。希望有所帮助!

答案 2 :(得分:4)

嗯,寻找通知中心并在通知中传回信息。 here is apples take on it   - 我个人采用这种方法,除非任何人有任何其他建议

答案 3 :(得分:2)

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