关闭ModalViewController并传回数据

发布于 2024-11-10 14:53:34 字数 701 浏览 4 评论 0原文

我有两个视图控制器,firstViewControllersecondViewController。我正在使用此代码切换到我的 secondaryViewController (我还向它传递了一个字符串):

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

然后我在 secondaryViewController 中使用此代码切换回第一个ViewController:

[self dismissModalViewControllerAnimated:YES];

所有这些都工作正常。我的问题是,如何将数据传递给firstViewController?我想将第二个视图控制器中的不同字符串传递到第一个视图控制器中。

I have two view controllers, firstViewController and secondViewController. I am using this code to switch to my secondViewController (I am also passing a string to it):

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

I then use this code in secondViewController to switch back to the firstViewController:

[self dismissModalViewControllerAnimated:YES];

All of this works fine. My question is, how would I pass data to the firstViewController? I would like to pass a different string into the firstViewController from the secondViewController.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

茶底世界 2024-11-17 14:53:34

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

在第二个视图控制器的头文件中声明一个协议。它应该如下所示:

#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) 的实现文件中,为 secondaryViewControllerDismissed 实现 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 是实现此目的的另一种方法,但作为最佳实践,当我想要跨多个 viewController 或对象进行通信时,我更喜欢使用它。如果您对使用 NSNotifications 感到好奇,这是我之前发布的答案: 从 appdelegate 中的线程触发跨多个视图控制器的事件

编辑:

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

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

这意味着您的 SecondDelegate 方法实现内部你的firstViewController现在看起来像:

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

You need to use delegate protocols... Here's how to do it:

Declare a protocol in your secondViewController's header file. It should look like this:

#import <UIKit/UIKit.h>

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


@interface SecondViewController : UIViewController
{
    id myDelegate;  
}

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

Don't forget to synthesize the myDelegate in your implementation (SecondViewController.m) file:

@synthesize myDelegate;

In your FirstViewController's header file subscribe to the SecondDelegate protocol by doing this:

#import "SecondViewController.h"

@interface FirstViewController:UIViewController <SecondDelegate>

Now when you instantiate SecondViewController in FirstViewController you should do the following:

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

Lastly, in the implementation file for your first view controller (FirstViewController.m) implement the SecondDelegate's method for secondViewControllerDismissed:

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

Now when you're about to dismiss the second view controller you want to invoke the method implemented in the first view controller. This part is simple. All you do is, in your second view controller, add some code before the dismiss code:

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

Delegate protocols are EXTREMELY, EXTREMELY, EXTREMELY useful. It would do you good to familiarize yourself with them :)

NSNotifications are another way to do this, but as a best practice, I prefer using it when I want to communicate across multiple viewControllers or objects. Here's an answer I posted earlier if you're curious about using NSNotifications: Firing events accross multiple viewcontrollers from a thread in the appdelegate

EDIT:

If you want to pass multiple arguments, the code before dismiss looks like this:

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

This means that your SecondDelegate method implementation inside your firstViewController will now look like:

- (void) secondViewControllerDismissed:(NSString*)stringForFirst argument2:(NSObject*)inObject1 argument3:(NSObject*)inObject2
{
    NSString thisIsTheDesiredString = stringForFirst;
    NSObject desiredObject1 = inObject1;
    //....and so on
}
忆梦 2024-11-17 14:53:34

我可能有点格格不入,但我开始更喜欢块语法而不是非常冗长的委托/协议方法。如果您从 vc1 制作 vc2,则可以在 vc2 上设置一个可以从 vc1 中设置的属性,该属性是一个块!

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

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

self.somethingHappenedInVC2(@"Hello!");

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

编辑 - 改进的示例

假设我们有一个 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);
}

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

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

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

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

I could be way out of place here, but I am starting to much prefer the block syntax to the very verbose delegate/protocol approach. If you make vc2 from vc1, have a property on vc2 that you can set from vc1 that is a block!

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

Then, when something happens in vc2 that you want to tell vc1 about, just execute the block that you defined in vc1!

self.somethingHappenedInVC2(@"Hello!");

This allows you to send data from vc2 back to vc1. Just like magic. IMO, this is a lot easier/cleaner than protocols. Blocks are awesome and need to be embraced as much as possible.

EDIT - Improved example

Let's say we have a mainVC that we want to present a modalVC on top of temporarily to get some input from a user. In order to present that modalVC from mainVC, we need to alloc/init it inside of mainVC. Pretty basic stuff. Well when we make this modalVC object, we can also set a block property on it that allows us to easily communicate between both vc objects. So let's take the example from above and put the follwing property in the .h file of modalVC:

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

Then, in our mainVC, after we have alloc/init'd a new modalVC object, you set the block property of modalVC like this:

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

So we are just setting the block property, and defining what happens when that block is executed.

Finally, in our modalVC, we could have a tableViewController that is backed by a dataSource array of strings. Once a row selection is made, we could do something like this:

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

And of course, each time we select a row in modalVC, we are going to get a console output from our NSLog line back in mainVC. Hope that helps!

遗忘曾经 2024-11-17 14:53:34

嗯,寻找通知中心并在通知中传回信息。 这是苹果的做法
- 我个人采取这种方法,除非有人有任何其他建议

hmm, look for the notification centre and pass back info in a notification. here is apples take on it
- I take this approach personally unless any one has any other suggestions

夏末 2024-11-17 14:53:34

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

Define a delegate protocol in the second view controller and make the first one the delegate of the second.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文