5

我有一个连接到服务器的 iOS 应用程序。如果我们断开连接,我希望能够关闭顶部视图控制器以返回“连接到服务器”视图控制器。问题是任何时候都可能发生断开连接,包括在视图控制器之间的转换期间。

视图控制器层次结构是这样的:

  1. ConnectingToServerViewController
  2. SignInViewController
  3. MainAppViewController
  4. 其他视图控制器

当检测到断开连接时,我希望视图层次结构折叠回:

  1. ConnectingToServerViewController

因此,当检测到断开连接时,会在 上调用此方法ConnectingToServerViewController以消除它所呈现的任何内容并返回尝试连接到服务器:

- (void)restartSession
{
    if (self.presentedViewController) {
        [self dismissViewControllerAnimated:NO completion:nil];
    }
}

但是,如果我在视图转换发生时尝试关闭,我会收到错误,例如

*** Assertion failure in -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:], /SourceCache/UIKit/UIKit-2380.17/UIWindowController.m:211

attempt to dismiss modal view controller whose view does not currently appear. self = <YYYYYViewController: 0x2089c8a0> modalViewController = <XXXXXViewController: 0x208e6610>
attempt to dismiss modal view controller whose view does not currently appear. self = <WWWWWWViewController: 0x1fd9e990> modalViewController = <YYYYYViewController: 0x2089c8a0>

第一个将使应用程序崩溃,第二个不会关闭任何内容并继续显示当前呈现的视图控制器。

想法:

  1. 延迟不起作用,因为我们不知道何时开始延迟
  2. 有没有办法跟踪视图转换何时完成?
  3. 所有视图控制器都应该覆盖 willAppear、didAppear 并在可以安全关闭时提醒应用程序吗?
  4. 也许我应该设置一个新的根视图控制器而不是解雇?
  5. 我确保所有被覆盖的 view(will|did)(dis)?appear 方法都调用了适当的超级方法。
  6. 任何需要所有视图控制器覆盖视图(已|将)显示方法来跟踪状态的解决方案听起来都可能会导致问题,如果我们忘记为新视图控制器设置基类。
4

4 回答 4

0

It seems like you are trying to dismiss the view controller when it is not currently on screen. To check if it is on screen you could use:

if (self.presentedViewController.view.window) 
{
    [self dismissViewControllerAnimated:NO completion:nil];
}
else 
{
    self.presentedViewController = nil;
}
于 2013-07-23T04:47:55.473 回答
0

做这样的事情。试试这个,

UIViewController *controller = self.presentingViewController; //THIS LINE IS IMP
[self dismissViewControllerAnimated:YES
                                 completion:^{
                                     [controller presentViewController:adminViewController animated:YES completion:nil];
                                     adminViewController.view.superview.frame    = CGRectMake(1024/2 - 400, 768/2 - 280, 800 , 560);//it's important to do this after
                                     [adminViewController release];
                                 }]; 
于 2013-07-23T04:48:49.540 回答
0

对我有用的一种方法是将一个新的视图控制器分配给根视图控制器。这样,当我们有新的控制器时,旧层次结构中的视图可以动画并过渡到它们的核心内容。

例如

- (void)restartSession
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    ConnectingToServerViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"ConnectingToServerViewController"];
    vc.modalPresentationStyle = UIModalPresentationFullScreen;
    [UIApplication sharedApplication].delegate.window.rootViewController = vc;
}

我不确定我是否知道这一切的缺点。也许旧的视图控制器永远不会因为悬挂的强引用而被释放?我们不再重用 ConnectingToServerViewController,我们每次都必须重新创建它。

我基于我在这个答案中看到的代码来管理和关闭 iOS 中的多个视图控制器

于 2013-07-23T07:20:06.537 回答
0

我会按顺序回答。

有没有办法跟踪视图转换何时完成?

您可以尝试使用UINavigationControllerDelegate(如果您正在使用其中之一)。其他方法可能是使用自定义动画师。

所有视图控制器都应该覆盖 willAppear、didAppear 并在可以安全关闭时提醒应用程序吗?

这是一个选择。如果你愿意,你可以自由地去做。另一种选择是不这样做。我认为诸如导航控制器之类的容器视图控制器有更好的方法。

我应该设置一个新的根视图控制器吗?

我建议做相反的事情。我会将其设置SignInViewController / MainAppViewController为根流,并根据需要以模态方式呈现 ConnectingToServerViewController。在我看来,这是一种更健康的方法。

希望能帮助到你。

于 2017-01-27T01:33:31.277 回答