为啥解散presentingViewController,只解散子控制器?
Posted
技术标签:
【中文标题】为啥解散presentingViewController,只解散子控制器?【英文标题】:Why dismissing the presentingViewController, only dismisses the child controller?为什么解散presentingViewController,只解散子控制器? 【发布时间】:2013-07-19 00:06:32 【问题描述】:我已经看到了一些与此相关的问题,但没有一个可以帮助我解决此问题。
我有一个 MasterViewController -> AViewController -> BViewController
文档说:
呈现视图控制器负责关闭它呈现的视图控制器。但是,如果您在呈现的视图控制器本身上调用此方法,它会自动将消息转发到呈现的视图控制器。
[self.presentingViewController dismissModalViewControllerAnimated: YES];
从我的 B VC 调用这个方法,应该关闭我的 A 和 B VC。然而,它只会解雇孩子(B VC)。为什么?
- (IBAction)checkButton:(UIButton *)sender
NSManagedObjectContext * context = [myAppDelegate managedObjectContext];
Work * newWork = [NSEntityDescription insertNewObjectForEntityForName:@"Work" inManagedObjectContext:context];
[newWork setName:_workName];
[myAppDelegate saveContext];
NSLog(@"%@", [self.presentingViewController description]);
[self.presentingViewController dismissModalViewControllerAnimated: YES];
我不知道这是否相关,但 A 和 B 风投是这样介绍的:
TWWorkNameViewController *controller = (TWWorkNameViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"WorkName"];
[self presentViewController:controller animated:YES completion:nil];
【问题讨论】:
不,它应该只关闭 BViewController。如果 A 展示了 B,那么写 [selfdismiss..](在 B 中)和 [self.presentingViewControllerdismiss..](也在 B 中)是相同的。 但是self.presentingViewController不应该是A VC吗?我从 B 获得了 A 的描述,我可以确认该方法是从 B 在 A 中调用的。我在这里缺少什么? 是的 self.presentingViewController 将是 A,并且由于 A 呈现了 B,A 正在解除它呈现的那个,即 B。当你在呈现的控制器中说 [self dismiss...] 时(B ),该消息被发送到控制器 A,它执行 [self dismiss...],但现在 self 是 A,因为它被转发了。 现在已修复。谢谢好心的先生,您非常清楚的解释并帮助我理解了这一点。 =) 【参考方案1】:这是因为您的 MasterViewController 正在呈现 AViewController 而这是呈现 BViewController 所以当您使用 [self.presentingViewController dismissModalViewControllerAnimated: YES];您正在关闭 BViewController,因为这是堆栈顶部的那个,如果您想从 BViewController 返回 MasterViewController,您可以使用 Navigtioncontroller 并使用方法
popToRootViewControllerAnimated: “弹出堆栈上除根视图控制器之外的所有视图控制器并更新显示。” http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html
如果您不想使用导航控制器,则需要使用通知: 在您的 MasterViewcontroller 视图中确实加载了这样做:
- (void)viewDidLoad
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(dismiss) name:@"BACKTOINDEXNOTE" object:nil];
-(void)dismiss
[self dismissViewControllerAnimated:YES completion:nil];
BViewController 在你的方法里面说
- (IBAction)checkButton:(UIButton *)sender
NSNotification * notification = [NSNotification notificationWithName:@"BACKTOINDEXNOTE" object:nil];
[[NSNotificationCenter defaultCenter] postNotification:notification];
因此,您将关闭 BViewController 和 AViewController。
【讨论】:
我现在明白了。我喜欢你的解决方案,但如果可以的话,我也会把这个留在这里,[[[self presentingVC] presentingVC] dismis...];这沿着堆栈向下(到主 VC)并解散 A 和 B VC。如果有任何理由我不应该这样做。请告诉我。谢谢!【参考方案2】:按照我的理解,“但是,如果您在呈现的视图控制器本身上调用此方法,它会自动将消息转发到呈现的视图控制器。”指的是呈现的视图控制器本身不呈现任何视图控制器的情况。通常,呈现视图控制器负责关闭它呈现的视图控制器,但如果你在一个没有呈现任何东西的视图控制器上调用dismissModalViewControllerAnimated
,则有两个选项 - 要么什么都不做,要么自行关闭它。它通过将该消息转发到其呈现的视图控制器来消除自己是有道理的。如果您在呈现另一个视图控制器的视图控制器上调用 dismissModalViewControllerAnimated
,那么它应该关闭该视图控制器,而不是按照文档所述将消息转发给它正在呈现的视图控制器(如果有的话)。
【讨论】:
【参考方案3】:我不知道这是否是正确的答案,但如果你有 A->B->C 并且你在 C 上并想回到 A,这意味着同时解雇 C 和 B,你可以使用 B 的 presentingViewController。我在 iOS 8 上对此进行了测试。B 和 C 在一个动画中同时关闭。
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
【讨论】:
以上是关于为啥解散presentingViewController,只解散子控制器?的主要内容,如果未能解决你的问题,请参考以下文章
将值从presentingViewController 传回presentingViewController
presentingViewController 是不是与presentingViewController 一起旋转