ios 如何防止出现模态主动控制器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32024812/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 07:16:56  来源:igfitidea点击:

How to prevent present modally an active controller?

iosobjective-cpresentmodalviewcontroller

提问by Zaporozhchenko Oleksandr

We have 2 controllers: MainVC and ProfileVC. From MainVC we go to ProfileVC with profileButtonpress (left item on navigation bar).

我们有 2 个控制器:MainVC 和 ProfileVC。从 MainVC,我们通过profileButton按(导航栏上的左侧项目)转到 ProfileVC 。

In Profile VC we have 2 buttons on navigation bar : back to main (leftItem) and open an alertView (rightItem).

在 Profile VC 中,我们在导航栏上有 2 个按钮:返回 main (leftItem) 并打开一个 alertView (rightItem)。

So there is simple KIF test (just eternal left-right taps on navigation bar):

所以有一个简单的 KIF 测试(只是在导航栏上永恒的左右点击):

- (void)testProfileButtons
    {
        [tester waitForAnimationsToFinishWithTimeout:0.3];
        while (true)
        {
            [tester tapScreenAtPoint:CGPointMake(20, 20)];
            [tester waitForTimeInterval:0.1];
            [tester tapScreenAtPoint:CGPointMake(380, 20)];
            [tester waitForTimeInterval:0.1];
            [tester tapScreenAtPoint:CGPointMake(20, 20)];
            [tester waitForTimeInterval:0.1];
        }
    }

It crashes application with error:

它使应用程序崩溃并出现错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller <UINavigationController: 0x7fe862ef82d0>.'

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller <UINavigationController: 0x7fe862ef82d0>.'

*** First throw call stack:
(
    0   CoreFoundation                      0x0000000110944c65 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x00000001105dabb7 objc_exception_throw + 45
    2   UIKit                               0x000000010f44b80d -[UIViewController _presentViewController:withAnimationController:completion:] + 3238
    3   UIKit                               0x000000010f44d6c1 __62-[UIViewController presentViewController:animated:completion:]_block_invoke + 132
    4   UIKit                               0x000000010fa5e5ae -[_UIViewControllerTransitionCoordinator _applyBlocks:releaseBlocks:] + 217
    5   UIKit                               0x000000010fa5b8e5 -[_UIViewControllerTransitionContext _runAlongsideCompletions] + 123
    6   UIKit                               0x000000010fa5b670 -[_UIViewControllerTransitionContext completeTransition:] + 126
    7   UIKit                               0x000000010f2fe8a6 __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke93 + 687
    8   UIKit                               0x000000010f387193 -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 326
    9   UIKit                               0x000000010f36e0f6 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 209
    10  UIKit                               0x000000010f36e42c -[UIViewAnimationState animationDidStop:finished:] + 76
    11  UIKit                               0x000000011daf3fdf -[UIViewAnimationStateAccessibility animationDidStop:finished:] + 48
    12  QuartzCore                          0x000000010f03e892 _ZN2CA5Layer23run_animation_callbacksEPv + 308
    13  libdispatch.dylib                   0x0000000111c67964 _dispatch_client_callout + 8
    14  libdispatch.dylib                   0x0000000111c52a59 _dispatch_main_queue_callback_4CF + 704
    15  CoreFoundation                      0x00000001108ac1f9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    16  CoreFoundation                      0x000000011086ddcb __CFRunLoopRun + 2043
    17  CoreFoundation                      0x000000011086d366 CFRunLoopRunSpecific + 470
    18  TurboChat UI Tests                  0x000000011b73ef69 -[KIFTestActor tryRunningBlock:complete:timeout:error:] + 425
    19  TurboChat UI Tests                  0x000000011b73f179 -[KIFTestActor runBlock:complete:timeout:] + 137
    20  TurboChat UI Tests                  0x000000011b73f304 -[KIFTestActor runBlock:timeout:] + 84
    21  TurboChat UI Tests                  0x000000011b73f73e -[KIFTestActor waitForTimeInterval:] + 174
    22  TurboChat UI Tests                  0x000000011b73c2ad -[TCProfileButtonsTest testProfileButtons] + 909
    23  CoreFoundation                      0x000000011083adec __invoking___ + 140
    24  CoreFoundation                      0x000000011083ac42 -[NSInvocation invoke] + 290
    25  XCTest                              0x000000011b79217a -[XCTestCase invokeTest] + 253
    26  XCTest                              0x000000011b792379 -[XCTestCase performTest:] + 150
    27  XCTest                              0x000000011b79bc35 -[XCTest run] + 260
    28  XCTest                              0x000000011b79108b -[XCTestSuite performTest:] + 379
    29  XCTest                              0x000000011b79bc35 -[XCTest run] + 260
    30  XCTest                              0x000000011b79108b -[XCTestSuite performTest:] + 379
    31  XCTest                              0x000000011b79bc35 -[XCTest run] + 260
    32  XCTest                              0x000000011b79108b -[XCTestSuite performTest:] + 379
    33  XCTest                              0x000000011b79bc35 -[XCTest run] + 260
    34  XCTest                              0x000000011b78e129 __25-[XCTestDriver _runSuite]_block_invoke + 56
    35  XCTest                              0x000000011b798edd -[XCTestObservationCenter _observeTestExecutionForBlock:] + 162
    36  XCTest                              0x000000011b78e060 -[XCTestDriver _runSuite] + 269
    37  XCTest                              0x000000011b78ea8d -[XCTestDriver _checkForTestManager] + 234
    38  XCTest                              0x000000011b79eb20 +[XCTestProbe runTests:] + 182
    39  Foundation                          0x000000010e5f21e5 __NSFireDelayedPerform + 387
    40  CoreFoundation                      0x00000001108ac174 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    41  CoreFoundation                      0x00000001108abd35 __CFRunLoopDoTimer + 1045
    42  CoreFoundation                      0x000000011086dd3d __CFRunLoopRun + 1901
    43  CoreFoundation                      0x000000011086d366 CFRunLoopRunSpecific + 470
    44  GraphicsServices                    0x00000001123a8a3e GSEventRunModal + 161
    45  UIKit                               0x000000010f30e8c0 UIApplicationMain + 1282
    46  TurboChat                           0x000000010cd1e75f main + 111
    47  libdyld.dylib                       0x0000000111c97145 start + 1
)

I also get this when testing on a real device:

在真实设备上测试时我也得到了这个:

Presenting view controllers on detached view controllers is discouraged <TCProfileTableViewController: 0x14f6299c0>.

and getting alertView appearing over MainVC instead ProfileVC with black screen under it.

并让 alertView 出现在 MainVC 上,而不是 ProfileVC 下,下面是黑屏。

Thats how we present alert in ProfileVC :

这就是我们在 ProfileVC 中呈现警报的方式:

- (IBAction)menuButtonPressed:(id)sender
{
    [self.navigationController presentViewController:self.menuAlert animated:YES completion:nil];
}

AlertView :

警报视图:

self.menuAlert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"%@?", NSLocalizedString(@"PROFILE_BTN_MENU", nil)]
                                                             message:nil
                                                      preferredStyle:UIAlertControllerStyleActionSheet];

Any suggestions?

有什么建议?

采纳答案by Zaporozhchenko Oleksandr

I have found kind of solution for this

我已经找到了解决方案

- (IBAction)menuButtonPressed:(id)sender
{
    [self.parentViewController presentViewController:self.menuAlert animated:YES completion:nil];
}

Alert view sometimes appears on menuVC, but it doesn't crash application and work normally. Answer was found there: Warning :-Presenting view controllers on detached view controllers is discouraged

警报视图有时会出现在 menuVC 上,但它不会使应用程序崩溃并正常工作。在那里找到答案:警告:不鼓励在分离的视图控制器上展示视图控制器

回答by Tj3n

I think u will need to dismiss the LAST viewcontroller first before going back by present modal segue, the viewcontroller is active, so it crash:

我认为您需要先关闭 LAST 视图控制器,然后才能通过当前模式转场返回,视图控制器处于活动状态,因此它会崩溃:

Use this after call segue from mainVC or something u wanted to go back:

从 mainVC 调用 segue 或您想返回的内容后使用它:

[self dismissViewControllerAnimated:NO completion:nil]

or

或者

[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil]

or use push segue, it auto add a back button that automatically add back function

或者使用push segue,它会自动添加一个后退按钮,自动添加后退功能

回答by Vitor Hugo Schwaab

There may be another case for other developers:

其他开发者可能还有另外一种情况:

Is the target ViewController presented after a connection triggered by a button? The user may be clicking twice, making two connections and opening the same ViewController twice, if you have a shared instance of the said ViewController.

按钮触发连接后是否呈现目标ViewController?如果您有上述 ViewController 的共享实例,用户可能会单击两次,建立两个连接并打开同一个 ViewController 两次。

Prevent it by doing something like this:

通过执行以下操作来防止它:

var didSuccess = false

func success(result: LoginModel.Result) {
    if didSuccess {
        return
    }
    didSuccess = true
    present(MainTabBarController.sharedInstance, animated: true, completion: nil)
}

Or disabling the button during connection.

或者在连接过程中禁用该按钮。

回答by Linh Dao

To prevent this exception. Simply just dismiss the currently showed ViewController to go back to the caller of the ViewController that you are dismissing:

为了防止这种异常。只需关闭当前显示的 ViewController 即可返回到您要关闭的 ViewController 的调用者:

self.dismiss(animated: true, completion: nil)