视图控制器:演示,解雇 [英] view controllers: presentation, dismissal

查看:27
本文介绍了视图控制器:演示,解雇的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是为了学习 xCode 的某些特定方面,我正在创建一个具有 2 个功能视图控制器的简单应用程序.每个都包含一个按钮,可以按下该按钮切换到另一个.我没有使用转场.我正在使用从应用程序委托中检索到的指针.

Just for the purpose of learning some particular aspects of xCode, I am creating a simple app that has 2 functional view controllers. Each contains a button that can be pressed to switch to the other. I am not using segues. I am using pointers retrieved from the app delegate.

视觉插图(点击获得更高分辨率):

visual illustration (click for higher resolution):

当应用加载时,根视图控制器呈现视图 1.当您点击切换到视图 2"时,以下代码会导致视图 2 出现:

When the app loads, the root view controller presents view 1. When you click "switch to view 2," the following code causes view 2 to appear:

- (IBAction)buttonPressed:(id)sender
{
    AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
    [self presentViewController:appDelegate.view2 animated:YES completion:nil];
}

到目前为止,一切都很好.

So far, so good.

但是当您在第二个视图上单击切换到视图 1"时,相同的代码(将view2"替换为view1")会出现以下错误:

But when you click "switch to view 1" on the second view, this same code (replacing "view2" with "view1") gives the following error:

应用程序试图以模态方式呈现主动控制器.

Application tried to present modally an active controller.

总结一下(其中 --> = 表示),我们有 root --> view1 --> view2 -x-> view1

So to summarize (where --> = presents), we have root --> view1 --> view2 -x-> view1

我不在乎保留谁呈现谁的历史.我只是想让按钮将先前显示的视图控制器带到顶部(使其可见),从而保持其视图的状态.

I don't care about retaining the history of who presents whom. I simply want the buttons to bring to the top (make visible) a previously displayed view controller, maintaining the state of its views.

很高兴知道以下内容:

  1. 是否有一种解决方法可以让我使用presentViewController 实现预期的行为?例如,root --> view2 --> view1

  1. Is there a workaround that would enable me to achieve the intended behavior using presentViewController? E.g., root --> view2 --> view1

还有什么其他方法可以更实用地实现所需的行为?它/他们必须使用应用程序委托,因为在我的实际应用程序中这是不可避免的.

What other method(s) would be more practical for achieving the desired behavior? It/they must use the app delegate because in my real application that will be unavoidable.

我是否违反了规则,试图将视图控制器放在顶部而不集成到一些更大的架构中?例如,这种行为是否应该由导航控制器和推/弹出来处理?如果是这样,你能解释为什么 xCode 不希望我这样做吗?为什么我不能只显示我想要的任何视图控制器,而不一定与其他视图控制器有任何关系?(也许是因为这可能会导致滥用应用委托?)

Am I breaking the rules by trying to put a view controller on top without integrating into some larger architecture? E.g, is this sort of behavior supposed to be handled by navigation conrollers and pushing/popping? If so, can you explain why xCode doesn't want me to do this? Why can't I just display whatever view controller I want, without it necessarily having any relationship to other view controllers? (Maybe because that could lead to abuse of the app delegate?)

呈现"视图控制器的真正含义是什么?除了在演示者和演示者之间创建指针之外,它还需要哪些功能限制或能力?保持呈现视图控制器活动"的重要性是什么?

What does it really mean to "present" a view controller? What functional limitations or capabilities does it entail beyond creating pointers between presenting and presenter? What is the importance of leaving the presenting view controller "active"?

如果改为让 view1 上的按钮将 presentViewController 消息发送到根视图(我希望只是将表示链从根 --> view1 更改为根 --> view2,使 view1 仍然存在于内存中但不属于此链的一部分),我得到一个不同的错误:尝试呈现不在窗口层次结构中的视图!"这是什么意思?我找不到窗口层次结构的解释.

If instead make the button on view1 send the presentViewController message to the root view (which I hoped would just change the presentation chain from root --> view1 to root --> view2, leaving view1 still existing in memory but not part of this chain), I get a different error: "Attempt to present on whose view is not in the window hierarchy!" What does this mean? I can't find an explanation of window hierarchy.

好吧,我知道我在这里问了很多,但任何启发都会非常感激!!

Okay, I know I'm asking a lot here, but any amount of enlightenment will be greatly appreciated!!

推荐答案

正确的方法是让底层的 rootVC 做呈现和解除(当你尝试 - 没有解除部分 - 第 5 点).当您想要呈现另一个时,您可以通过将消息 + 完成块从 view1 和 view2 中的每一个发送回 rootVC 来实现这一点.

The correct way to do this is to get the underlying rootVC to do the presenting and dismissing (as you attempt - without the dismissing part - in point 5). You can achieve this by sending a message + completion block back to the rootVC from each of view1 and view2 when you want to present the other.

当您在视图 1 中时:

When you are in view1:

- (IBAction)buttonPressed:(id)sender 
    AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];

    UIViewController* presentingVC = self.presentingViewController;
    [presentingVC dismissViewControllerAnimated:YES completion:^{
          [presentingVC presentViewController:appDelegate.view2 
                                     animated:YES 
                                   completion:nil];
    }];
}

和 view2 类似.注意你需要这一行:

and similarly for view2. Take care that you need this line:

        UIViewController* presentingVC = self.presentingViewController;

因为您无法在完成块中引用self.presentingViewController",因为此时它的控制器已被解散.

as you can't refer to 'self.presentingViewController' inside the completion block as it's controller has been dismissed at this point.

我认为这回答了第 1 点和第 2 点.

I think that answers points 1 and 2.

回答第 3 点为什么我不能只显示我想要的任何视图控制器,而它不一定与其他视图控制器有任何关系?"- 你可以(通过窗口的 rootViewController 属性),但是将不得不实现导航和管理你的 viewController 指针,这意味着你最终会创建某种控制器.Apple 在这方面为您提供了一些满足大多数需求的产品.

To answer point 3 "Why can't I just display whatever view controller I want, without it necessarily having any relationship to other view controllers?" - well you can (via the rootViewController property of the window), but then you are going to have to implement navigation and manage your viewController pointers, which means you will end up creating a controller of some sort. Apple is helping you here by providing you with a few which cover most needs.

关于你的观点 4 - viewController 的呈现是由呈现的 VC 控制的,这就是为什么你想要保持那个活跃"的原因.当您发送此消息时:[self disconnectViewControllerAnimated:completion:], self 只是将消息重新路由到它的 presentingViewController.如果你去掉你的 presentingViewController,你的dismiss 方法就会中断.

As regards your point 4 - the presenting of a viewController is controlled by the presenting VC, which is why you want to keep that one 'active'. When you send this message: [self dismissViewControllerAnimated:completion:], self just reroutes the messge to it's presentingViewController. If you get rid of your presentingViewController your dismiss method will break.

上面已经回答了第 5 点.在要求呈现底层视图之前,您需要先关闭最顶层的视图.请注意,view1仍在内存中",但这仅仅是因为您在应用程序委托中保留了一个指向它的指针.

Point 5 is answered above. You need to dismiss the topmost view first before asking an underlying view to present. Note that view1 is "still in memory" but only because you have retained a pointer to it in your app delegate.

更新

当你试图让它与初始启动直接到视图1一起工作时,你可以创建一个 BOOL launched 属性并从你的 rootViewController 的 viewDidAppear<检查/设置它/代码>:

As you are trying to get this to work with an initial launch-straight-to-view1, you could make a BOOL launched property and check/set it from your rootViewController's viewDidAppear:

- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    if (!self.launched) {
        self.launched = TRUE;
        AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
        [self presentViewController:appDelegate.view1
                           animated:YES
                         completion:nil];
    }
}

这篇关于视图控制器:演示,解雇的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆