Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 解除ModalViewController并传回数据_Iphone_Ios_Uiviewcontroller_Modalviewcontroller - Fatal编程技术网

Iphone 解除ModalViewController并传回数据

Iphone 解除ModalViewController并传回数据,iphone,ios,uiviewcontroller,modalviewcontroller,Iphone,Ios,Uiviewcontroller,Modalviewcontroller,我有两个视图控制器,firstViewController和secondViewController。我正在使用此代码切换到我的secondViewController(我还向它传递一个字符串): 然后,我在secondViewController中使用此代码切换回firstViewController: [self dismissModalViewControllerAnimated:YES]; 所有这些都很好。我的问题是,如何将数据传递给firstViewController?我想将另一个

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

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

[self dismissModalViewControllerAnimated:YES];

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

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

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

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

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

#import <UIKit/UIKit.h>

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


@interface SecondViewController : UIViewController
{
    id myDelegate;  
}

@property (nonatomic, assign) id<SecondDelegate>    myDelegate;
if([self.myDelegate respondsToSelector:@selector(secondViewControllerDismissed:argument2:argument3:)])
{
    [self.myDelegate secondViewControllerDismissed:@"THIS IS THE STRING TO SEND!!!" argument2:someObject argument3:anotherObject];
}
[self dismissModalViewControllerAnimated:YES];
ModalVC *modalVC = [[ModalVC alloc] init];
modalVC.somethingHappenedInModalVC = ^(NSString *response) {
     NSLog(@"Something was selected in the modalVC, and this is what it was:%@", response);
}
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
      NSString *selectedString = self.dataSource[indexPath.row];
      self.somethingHappenedInModalVC(selectedString);
 }
在FirstViewController的头文件中,通过执行以下操作订阅SecondDelegate协议:

#import "SecondViewController.h"

@interface FirstViewController:UIViewController <SecondDelegate>
最后,在第一个视图控制器的实现文件(FirstViewController.m)中,为secondviewcontrollerdissed实现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感兴趣,我在前面发布了一个答案:

编辑:

如果要传递多个参数,请在Disclose之前执行以下代码:

#import <UIKit/UIKit.h>

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


@interface SecondViewController : UIViewController
{
    id myDelegate;  
}

@property (nonatomic, assign) id<SecondDelegate>    myDelegate;
if([self.myDelegate respondsToSelector:@selector(secondViewControllerDismissed:argument2:argument3:)])
{
    [self.myDelegate secondViewControllerDismissed:@"THIS IS THE STRING TO SEND!!!" argument2:someObject argument3:anotherObject];
}
[self dismissModalViewControllerAnimated:YES];
ModalVC *modalVC = [[ModalVC alloc] init];
modalVC.somethingHappenedInModalVC = ^(NSString *response) {
     NSLog(@"Something was selected in the modalVC, and this is what it was:%@", response);
}
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
      NSString *selectedString = self.dataSource[indexPath.row];
      self.somethingHappenedInModalVC(selectedString);
 }
这意味着firstViewController中的SecondDelegate方法实现现在看起来像:

- (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。就像魔术一样。依我看,这比协议容易/干净得多。积木非常棒,需要尽可能多的拥抱

编辑-改进示例

假设我们有一个mainVC,我们想在上面临时显示一个modalVC,以便从用户那里获得一些输入。为了从mainVC展示modalVC,我们需要在mainVC内部alloc/init它。非常基本的东西。当我们制作这个modalVC对象时,我们还可以在它上面设置一个block属性,它允许我们在两个vc对象之间轻松地通信。因此,让我们以上面的示例为例,将以下属性放在modalVC的.h文件中:

 @property (nonatomic, copy) void (^somethingHappenedInModalVC)(NSString *response);  
然后,在我们的mainVC中,在分配/初始化一个新的modalVC对象之后,您可以如下设置modalVC的block属性:

#import <UIKit/UIKit.h>

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


@interface SecondViewController : UIViewController
{
    id myDelegate;  
}

@property (nonatomic, assign) id<SecondDelegate>    myDelegate;
if([self.myDelegate respondsToSelector:@selector(secondViewControllerDismissed:argument2:argument3:)])
{
    [self.myDelegate secondViewControllerDismissed:@"THIS IS THE STRING TO SEND!!!" argument2:someObject argument3:anotherObject];
}
[self dismissModalViewControllerAnimated:YES];
ModalVC *modalVC = [[ModalVC alloc] init];
modalVC.somethingHappenedInModalVC = ^(NSString *response) {
     NSLog(@"Something was selected in the modalVC, and this is what it was:%@", response);
}
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
      NSString *selectedString = self.dataSource[indexPath.row];
      self.somethingHappenedInModalVC(selectedString);
 }
因此,我们只是设置块属性,并定义执行该块时会发生什么

最后,在我们的modalVC中,我们可以有一个由字符串数据源数组支持的tableViewController。选择行后,我们可以执行以下操作:

#import <UIKit/UIKit.h>

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


@interface SecondViewController : UIViewController
{
    id myDelegate;  
}

@property (nonatomic, assign) id<SecondDelegate>    myDelegate;
if([self.myDelegate respondsToSelector:@selector(secondViewControllerDismissed:argument2:argument3:)])
{
    [self.myDelegate secondViewControllerDismissed:@"THIS IS THE STRING TO SEND!!!" argument2:someObject argument3:anotherObject];
}
[self dismissModalViewControllerAnimated:YES];
ModalVC *modalVC = [[ModalVC alloc] init];
modalVC.somethingHappenedInModalVC = ^(NSString *response) {
     NSLog(@"Something was selected in the modalVC, and this is what it was:%@", response);
}
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
      NSString *selectedString = self.dataSource[indexPath.row];
      self.somethingHappenedInModalVC(selectedString);
 }

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

链接实际上过于复杂了,您只需要一个观察者(第一个视图控制器)并从第二个视图发送notif。您可以为通知分配选择器,并通过通知返回信息。根据Apple的建议,应该在演示视图控制器中而不是在演示视图控制器中取消secondViewController。听起来您还没有设置UITableView的委托。你能把这个作为一个问题贴出来,用你的代码圈回来吗?“我也许能帮你。”Michael文档中说,在self上调用Disclease会将调用转发给演示视图控制器。此外,调用self更干净,因为这样您就不必担心根据您的目标iOS版本(5或之前)在presentingViewController和parentViewController之间切换;积木非常有用。我正在考虑在某个时候改变这个答案以支持块。但是在本例中,我暂时没有看到委托答案,因为它给了我们更多的自由来操作可以传递到模态中的对象。我只是很懒,很快就会更新这个答案来使用blocks:)@sid谢谢兄弟它对我有用,但你需要稍微修改一下。很多事情都变了。请编辑它当使用情节串连板时,它是否仍然有效?现在它对我不起作用。只是因为一个lldb错误而退出。我能看到的主要区别是vc的alloc现在是一个实例化的故事板流。编辑并在创建块之前演示。修正。我同意你的观点:)我很久以前就发布了我的答案。现在,我根据使用情况在使用块/协议之间切换。鉴于此线程至今仍相当活跃,我应该在某个时候编辑我的答案以包含块。此答案需要被接受,因为这带来了最直观的解决方案。在两个合适的答案中,这是最好的一个!到目前为止,这是我比较喜欢的方法。在swift中,这是通过闭包实现的。比委托和通知要好得多,因为您不需要指定协议或这些“丑陋”的通知常量。如果您在呈现的vc中对保存闭包的变量的名称进行修改,那么它可以是非常直观的代码,例如vc.didCancel、vc.didFinish。。。你可以设置