Cố gắng trình bày UIViewContoder trên UIViewContoder có chế độ xem không nằm trong phân cấp cửa sổ


599

Mới bắt đầu sử dụng Xcode 4.5 và tôi đã gặp lỗi này trong bảng điều khiển:

Cảnh báo: Cố gắng trình bày <finishViewControll: 0x1e56e0a0> trên <ViewContoder: 0x1ec3e000> có chế độ xem không nằm trong phân cấp cửa sổ!

Chế độ xem vẫn đang được trình bày và mọi thứ trong ứng dụng đang hoạt động tốt. Đây có phải là một cái gì đó mới trong iOS 6?

Đây là mã tôi đang sử dụng để thay đổi giữa các chế độ xem:

UIStoryboard *storyboard = self.storyboard;
finishViewController *finished = 
[storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];

[self presentViewController:finished animated:NO completion:NULL];

3
Tôi có cùng một vấn đề chính xác, ngoại trừ cố gắng gọi presentViewController:animated:completionbộ điều khiển điều hướng. Bạn đang làm điều này trong đại biểu ứng dụng?
tarnfeld

Không tôi đang làm điều đó từ bộ điều khiển xem này sang bộ điều khiển khác. Bạn đã tìm thấy giải pháp nào chưa?
Kyle Goslan

Vấn đề tương tự đối với một phần mã luôn hoạt động trước khi sử dụng Xcode 4.5, tôi đang trình bày một UINavestionControll, nhưng một lần nữa điều này luôn hoạt động trước đó.
Emanuele Fumagalli

Tôi có cùng một vấn đề, không được giải quyết. Làm điều đó từ đại biểu ứng dụng và bộ điều khiển rootview gọi "PresentViewControll" đang tạo ra một UITabBarContoder.
darksider

3
đồng thời, nếu gọi phương thức này trước khi gọi makeKeyAndVisible, hãy di chuyển nó sau đó
mike_haney

Câu trả lời:


1296

Bạn đang gọi phương pháp này từ đâu? Tôi đã có một vấn đề trong đó tôi đã cố gắng trình bày một bộ điều khiển khung nhìn phương thức trong viewDidLoadphương thức. Giải pháp cho tôi là chuyển cuộc gọi này đếnviewDidAppear: phương thức.

Giả định của tôi là chế độ xem của trình điều khiển khung nhìn không nằm trong hệ thống phân cấp khung nhìn của cửa sổ tại điểm mà nó đã được tải (khi viewDidLoadtin nhắn được gửi), nhưng nó nằm trong hệ thống phân cấp cửa sổ sau khi nó được trình bày (khi viewDidAppear:tin nhắn được gửi) .


Thận trọng

Nếu bạn thực hiện một cuộc gọi đến presentViewController:animated:completion:trongviewDidAppear: bạn có thể gặp phải sự cố trong đó trình điều khiển chế độ xem phương thức luôn được trình bày bất cứ khi nào chế độ xem của trình điều khiển chế độ xem xuất hiện (điều này có ý nghĩa!) Và do đó trình điều khiển chế độ xem được trình bày sẽ không bao giờ biến mất .. .

Có thể đây không phải là nơi tốt nhất để trình bày bộ điều khiển chế độ xem phương thức, hoặc có lẽ một số trạng thái bổ sung cần được giữ để cho phép trình điều khiển chế độ xem trình bày quyết định có nên trình bày bộ điều khiển chế độ xem phương thức ngay lập tức hay không.


6
@James bạn đúng, chế độ xem rõ ràng không nằm trong hệ thống phân cấp cho đến khi viewWillAppear được giải quyết và một khi viewDidAppear được gọi. Nếu đây là câu hỏi của tôi, tôi sẽ chấp nhận câu trả lời này;)
Matt Mc

6
@james Cảm ơn. Sử dụng ViewDidAppear cũng giải quyết được vấn đề cho tôi. Có ý nghĩa.
Ali

44
Tôi ước tôi có thể nâng cấp điều này hai lần. Tôi chỉ gặp vấn đề này và đến chủ đề để thấy rằng tôi đã nâng cấp lần cuối cùng tôi nhìn thấy điều này.
Schrockwell

7
Lưu ý rằng khi bạn thay đổi VC trong viewDidAppear, điều này gây ra việc thực thi một segue, với Animation. Gây ra một đèn flash / hiển thị của nền.
Vincent

2
Vâng, mẹo là viewWillAppear: (BOOL) hoạt hình là chính xác. Một điều quan trọng hơn bạn phải gọi siêu trong phương thức, là [super viewDidAppear: hoạt hình]; không có cái này thì nó không hoạt động.
BootMaker

66

Một nguyên nhân tiềm năng khác:

Tôi đã gặp vấn đề này khi tôi vô tình trình bày cùng một bộ điều khiển khung nhìn hai lần. (Một lần performSegueWithIdentifer:sender:được gọi khi nhấn nút và lần thứ hai với một segue được kết nối trực tiếp với nút).

Thực tế, hai vụ nổ súng đã nổ ra cùng một lúc và tôi đã gặp lỗi: Attempt to present X on Y whose view is not in the window hierarchy!


4
Tôi cũng có lỗi tương tự, và câu trả lời của bạn ở đây đã giúp tôi tìm hiểu chuyện gì đang xảy ra, đó thực sự là lỗi này, đã sửa nó vì bạn ạ, cảm ơn bạn, +1
samouray

1
Tôi đã xóa segue cũ và kết nối VC với VC. Có cách nào để kết nối nút với câu chuyệnBoard với VC không vì cách đó chỉ khiến tôi gặp lỗi?
MCB

Tôi đã có lỗi tương tự, câu trả lời của bạn đã giải quyết vấn đề của tôi, cảm ơn sự quan tâm của bạn. Trân trọng.
iamburak

1
lol, vô tình tôi cũng đang tạo ra hai vc: từ nút và biểu diễn, cảm ơn vì tiền boa !!!
Borzh

1
Trong trường hợp của tôi, tôi đã gọi present(viewController, animated: true, completion: nil)bên trong một vòng lặp.
Samo

38

viewWillLayoutSubviewsviewDidLayoutSubviews(iOS 5.0+) có thể được sử dụng cho mục đích này. Chúng được gọi sớm hơn viewDidAppear.


3
Tuy nhiên, chúng cũng được sử dụng trong các dịp khác vì vậy tôi nghĩ rằng chúng có thể được gọi nhiều lần trong "vòng đời" của chế độ xem.
Jonny

Đó cũng không phải là những gì các phương thức dành cho - như tên cho thấy. viewDidAppear là chính xác. Đọc lên trên vòng đời xem là một ý tưởng tốt.
cụ

Đây là giải pháp tốt nhất. Trong trường hợp của tôi, việc trình bày trong viewDidAppear gây ra sự phân tách thứ hai hiển thị của trình điều khiển khung nhìn trước khi phương thức được tải, điều này không được chấp nhận.
TMilligan

Câu trả lời này hoạt động tốt nhất cho tôi khi cố gắng hiển thị cảnh báo. Cảnh báo sẽ không hiển thị khi tôi đặt nó vào viewDidLoad và viewWillAppear.
uplearnedu.com

26

Để hiển thị bất kỳ chế độ xem phụ nào cho chế độ xem chính, Vui lòng sử dụng mã sau đây

UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

while (yourCurrentViewController.presentedViewController) 
{
   yourCurrentViewController = yourCurrentViewController.presentedViewController;
}

[yourCurrentViewController presentViewController:composeViewController animated:YES completion:nil];

Để loại bỏ bất kỳ lượt xem phụ nào khỏi chế độ xem chính, vui lòng sử dụng mã sau

UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

while (yourCurrentViewController.presentedViewController) 
{
   yourCurrentViewController = yourCurrentViewController.presentedViewController;
}

[yourCurrentViewController dismissViewControllerAnimated:YES completion:nil];

Làm việc cho tôi cũng được
Aziz Javed

17

Tôi cũng gặp phải vấn đề này khi tôi cố gắng trình bày một UIViewControllertrong viewDidLoad. Câu trả lời của James Bedford đã có hiệu quả, nhưng ứng dụng của tôi hiển thị nền trước trong 1 hoặc 2 giây.

Sau một số nghiên cứu, tôi đã tìm ra cách để giải quyết vấn đề này bằng cách sử dụng addChildViewController.

- (void)viewDidLoad
{
    ...
    [self.view addSubview: navigationViewController.view];
    [self addChildViewController: navigationViewController];
    ...
}

9
Tôi nghĩ rằng bạn đang thiếu [navigationViewControll didMoveToParentViewControll: self]
foFox

2
Tôi đã thử mã của bạn, cùng với đề xuất của foFox và khi tôi xóa mã đó khỏi cha mẹ, nó sẽ không biến mất. Lololol. Vẫn bị mắc kẹt không có sửa chữa.
Logicsaurus Rex

Hoạt động trong Swift3.1
Kang Byul

@sunkehappy trên hai dòng được sử dụng trước trình điều khiển hiện tại, nhưng nó bị lỗi tại sao?
Iyyappan Ravi

14

Có lẽ, giống như tôi, bạn có một gốc sai viewController

Tôi muốn hiển thị ViewControllertrong một non-UIViewControllerbối cảnh,

Vì vậy, tôi không thể sử dụng mã như vậy:

[self presentViewController:]

Vì vậy, tôi nhận được một UIViewControll:

[[[[UIApplication sharedApplication] delegate] window] rootViewController]

Đối với một số lý do (lỗi logic), rootViewControllerđó là một cái gì đó ngoài dự kiến ​​(một bình thường UIViewController). Sau đó, tôi sửa lỗi, thay thế rootViewControllerbằng một UINavigationController, và vấn đề đã biến mất.


8

TL; DR Bạn chỉ có thể có 1 rootViewControll và một cái được trình bày gần đây nhất. Vì vậy, đừng thử có một trình điều khiển khung nhìn trình bày một trình điều khiển khác khi nó đã được trình bày một trình điều khiển chưa bị loại bỏ.

Sau khi thực hiện một số thử nghiệm của riêng tôi, tôi đã đi đến kết luận.

Nếu bạn có một rootViewController mà bạn muốn tất cả mọi thứ hiện tại thì bạn có thể chạy vào vấn đề này.

Đây là mã rootControll của tôi (mở là lối tắt của tôi để trình bày một trình điều khiển khung nhìn từ gốc).

func open(controller:UIViewController)
{
    if (Context.ROOTWINDOW.rootViewController == nil)
    {
        Context.ROOTWINDOW.rootViewController = ROOT_VIEW_CONTROLLER
        Context.ROOTWINDOW.makeKeyAndVisible()
    }

    ROOT_VIEW_CONTROLLER.presentViewController(controller, animated: true, completion: {})
}

Nếu tôi gọi mở hai lần liên tiếp (bất kể thời gian đã trôi qua), điều này sẽ hoạt động tốt ở lần mở đầu tiên, nhưng KHÔNG ở lần mở thứ hai. Lần thử mở thứ hai sẽ dẫn đến lỗi ở trên.

Tuy nhiên, nếu tôi đóng chế độ xem được trình bày gần đây nhất sau đó gọi mở, nó sẽ hoạt động tốt khi tôi gọi lại mở (trên một trình điều khiển chế độ xem khác).

func close(controller:UIViewController)
{
    ROOT_VIEW_CONTROLLER.dismissViewControllerAnimated(true, completion: nil)
}

Những gì tôi đã kết luận là rootViewContaptor chỉ MOST-RECENT-CALL nằm trong chế độ xem Phân cấp (ngay cả khi bạn không loại bỏ nó hoặc xóa chế độ xem). Tôi đã thử chơi với tất cả các cuộc gọi của trình tải (viewDidLoad, viewDidAppear và thực hiện các cuộc gọi chuyển phát chậm) và tôi thấy rằng cách duy nhất tôi có thể khiến nó hoạt động là CHỈ gọi hiện tại từ bộ điều khiển xem nhiều nhất.


Điều này có vẻ như là một vấn đề phổ biến hơn rằng nhiều câu trả lời có ra bình chọn của bạn. Thật không may, điều này cực kỳ hữu ích
rayepps

vâng tất cả đều tốt và tốt nhưng giải pháp là gì ... tôi có một luồng nhân viên nền đến máy chủ và hiển thị bảng phân cảnh bên trái và trung tâm và toàn bộ phương pháp là không có thật .. thật đáng tiếc .. hoàn toàn là một làn gió đùa vì al tôi muốn làm chủ đề nền tảng của anh ấy là: wait wait decide push screen to frontvà nó KHÔNG HỀ là iOS ????
Ông Heelis

5

Vấn đề của tôi là tôi đã được thực hiện segue trong UIApplicationDelegate's didFinishLaunchingWithOptionsphương pháp trước khi tôi gọi makeKeyAndVisible()trên cửa sổ.


làm sao? bạn có thể xây dựng? Tôi đang đối mặt với cùng một vấn đề. đây là mã của tôi để cho initialViewControlleripad: UIViewController = mainStoryboardIpad.instantiateViewController (withIdentifier: "SplashController") như UIViewController self.window .rootViewController = initialViewControlleripad self.window .makeKeyAndVisible ()?
shahtaj khalid

4

Trong tình huống của tôi, tôi đã không thể đặt tôi trong một ghi đè lớp. Vì vậy, đây là những gì tôi nhận được:

let viewController = self // I had viewController passed in as a function,
                          // but otherwise you can do this


// Present the view controller
let currentViewController = UIApplication.shared.keyWindow?.rootViewController
currentViewController?.dismiss(animated: true, completion: nil)

if viewController.presentedViewController == nil {
    currentViewController?.present(alert, animated: true, completion: nil)
} else {
    viewController.present(alert, animated: true, completion: nil)
}

3

Tôi đã từng gặp vấn đề tương tự. Tôi đã phải nhúng một điều khiển chuyển hướng và trình bày bộ điều khiển thông qua nó. Dưới đây là đoạn code mẫu.

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    UIImagePickerController *cameraView = [[UIImagePickerController alloc]init];
    [cameraView setSourceType:UIImagePickerControllerSourceTypeCamera];
    [cameraView setShowsCameraControls:NO];

    UIView *cameraOverlay = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 768, 1024)];
    UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"someImage"]];
    [imageView setFrame:CGRectMake(0, 0, 768, 1024)];
    [cameraOverlay addSubview:imageView];

    [cameraView setCameraOverlayView:imageView];

    [self.navigationController presentViewController:cameraView animated:NO completion:nil];
//    [self presentViewController:cameraView animated:NO completion:nil]; //this will cause view is not in the window hierarchy error

}


3

Tôi gặp vấn đề tương tự. Vấn đề là, PerformanceSegueWithIdentifier đã được kích hoạt bởi một thông báo, ngay sau khi tôi đặt thông báo trên luồng chính, thông báo cảnh báo đã biến mất.


3

Nó làm việc tốt thử này. Liên kết

UIViewController *top = [UIApplication sharedApplication].keyWindow.rootViewController;
[top presentViewController:secondView animated:YES completion: nil];

3

Trong trường hợp nó giúp mọi người, vấn đề của tôi là vô cùng ngớ ngẩn. Tất nhiên là lỗi của tôi. Thông báo sẽ được kích hoạt một phương pháp được gọi phương thức. Nhưng tôi đã không xóa thông báo một cách chính xác, vì vậy tại một số điểm, tôi sẽ có nhiều hơn một thông báo, vì vậy phương thức sẽ được gọi nhiều lần. Tất nhiên, sau khi bạn gọi phương thức một lần, trình điều khiển khung nhìn gọi nó không còn trong hệ thống phân cấp chế độ xem, đó là lý do tại sao chúng ta thấy vấn đề này. Tình hình của tôi gây ra một loạt các vấn đề khác, như bạn mong đợi.

Vì vậy, để tóm tắt, bất cứ điều gì bạn đang làm hãy đảm bảo phương thức không được gọi nhiều hơn một lần .


3

Tôi đã kết thúc với một mã như vậy cuối cùng cũng hoạt động với tôi (Swift), xem xét bạn muốn hiển thị một số viewControllertừ hầu như mọi nơi. Mã này rõ ràng sẽ bị sập khi không có rootViewControll, đó là kết thúc mở. Nó cũng không bao gồm chuyển đổi thường được yêu cầu sang giao diện người dùng bằng cách sử dụng

dispatch_sync(dispatch_get_main_queue(), {
    guard !NSBundle.mainBundle().bundlePath.hasSuffix(".appex") else {
       return; // skip operation when embedded to App Extension
    }

    if let delegate = UIApplication.sharedApplication().delegate {
        delegate.window!!.rootViewController?.presentViewController(viewController, animated: true, completion: { () -> Void in
            // optional completion code
        })
    }
}

BTW để hiểu WHERE tôi gọi phương thức này từ ... đó là thư viện SDK không có UI, hiển thị UI của chính nó trên ứng dụng của bạn trong trường hợp nhất định (không được tiết lộ).
igrac817

Bạn SẼ sụp đổ và đốt cháy nếu có ai quyết định nhúng bạn SDK trong một ứng dụng mà có phần mở rộng. Truyền một UIViewContoder để lạm dụng vào phương thức khởi tạo sdk của bạn [s].
Anton Tropashko

Bạn đúng là Anton. Mã này được viết khi Tiện ích mở rộng không tồn tại và SDK chưa được sử dụng trong bất kỳ tiện ích nào. Tôi đã thêm một điều khoản bảo vệ để bỏ qua trường hợp cạnh này.
igrac817

3

Loại cảnh báo này có thể có nghĩa là bạn đang cố gắng trình bày mới View Controller thông qua Navigation Controllerđiều này trong khi Navigation Controllerđang trình bày khác View Controller. Để khắc phục, bạn phải loại bỏ hiện View Controllertại lúc đầu và khi hoàn thành trình bày cái mới. Một nguyên nhân khác của cảnh báo có thể là cố gắng trình bày View Controllertrên luồng khác hơn main.


3

Tôi gặp vấn đề tương tự trên Swift 4.2 nhưng quan điểm của tôi không được trình bày từ chu trình xem. Tôi thấy rằng tôi có nhiều segue được trình bày cùng một lúc. Vì vậy, tôi đã sử dụng ClarkAsyncAfter.

func updateView() {

 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in

// for programmatically presenting view controller 
// present(viewController, animated: true, completion: nil)

//For Story board segue. you will also have to setup prepare segue for this to work. 
 self?.performSegue(withIdentifier: "Identifier", sender: nil)
  }
}

2

Tôi cố định nó bằng cách di chuyển các start()chức năng bên trong dismisskhối hoàn thành:

self.tabBarController.dismiss(animated: false) {
  self.start()
}

Bắt đầu chứa hai cuộc gọi đến self.present()một cho UINavestionControll và một cuộc gọi khác cho mộtUIImagePickerController .

Đó là cố định nó cho tôi.


1

Bạn cũng có thể nhận được cảnh báo này khi thực hiện một segue từ bộ điều khiển xem được nhúng trong một thùng chứa. Giải pháp chính xác là sử dụng segue từ cha mẹ của container, không phải từ bộ điều khiển xem của container.


1

Phải viết dòng dưới đây.

self.searchController.definesPresentationContext = true

thay vì

self.definesPresentationContext = true

trong UIViewControll


1

Với Swift 3 ...

Một nguyên nhân có thể khác cho điều này, xảy ra với tôi, là có một sự khác biệt từ một bảngViewCell đến một ViewContoder khác trên Storyboard. Tôi cũng đã sử dụngoverride func prepare(for segue: UIStoryboardSegue, sender: Any?) {} khi các tế bào được nhấp.

Tôi đã khắc phục vấn đề này bằng cách tạo một segue từ ViewContoder thành ViewContoder.


1

Tôi đã gặp sự cố này và nguyên nhân gốc là đăng ký trình xử lý nhấp vào nút (TouchUpInside) nhiều lần.

Nó đã đăng ký vào ViewWillAppear, được gọi nhiều lần vì chúng tôi đã thêm điều hướng để đi đến bộ điều khiển khác và sau đó thư giãn trở lại.


1

Nó đã xảy ra với tôi rằng segue trong bảng phân cảnh là một loại bị hỏng . Xóa segue (và tạo lại chính xác segue một lần nữa) đã giải quyết vấn đề.


1

Với cửa sổ chính của bạn, nhiều khả năng sẽ luôn có những lần chuyển tiếp không tương thích với việc đưa ra cảnh báo. Để cho phép trình bày cảnh báo bất cứ lúc nào trong vòng đời ứng dụng của bạn, bạn nên có một cửa sổ riêng để thực hiện công việc.

/// independant window for alerts
@interface AlertWindow: UIWindow

+ (void)presentAlertWithTitle:(NSString *)title message:(NSString *)message;

@end

@implementation AlertWindow

+ (AlertWindow *)sharedInstance
{
    static AlertWindow *sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[AlertWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
    });
    return sharedInstance;
}

+ (void)presentAlertWithTitle:(NSString *)title message:(NSString *)message
{
    // Using a separate window to solve "Warning: Attempt to present <UIAlertController> on <UIViewController> whose view is not in the window hierarchy!"
    UIWindow *shared = AlertWindow.sharedInstance;
    shared.userInteractionEnabled = YES;
    UIViewController *root = shared.rootViewController;
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    alert.modalInPopover = true;
    [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        shared.userInteractionEnabled = NO;
        [root dismissViewControllerAnimated:YES completion:nil];
    }]];
    [root presentViewController:alert animated:YES completion:nil];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    self.userInteractionEnabled = NO;
    self.windowLevel = CGFLOAT_MAX;
    self.backgroundColor = UIColor.clearColor;
    self.hidden = NO;
    self.rootViewController = UIViewController.new;

    [NSNotificationCenter.defaultCenter addObserver:self
                                           selector:@selector(bringWindowToTop:)
                                               name:UIWindowDidBecomeVisibleNotification
                                             object:nil];

    return self;
}

/// Bring AlertWindow to top when another window is being shown.
- (void)bringWindowToTop:(NSNotification *)notification {
    if (![notification.object isKindOfClass:[AlertWindow class]]) {
        self.hidden = YES;
        self.hidden = NO;
    }
}

@end

Sử dụng cơ bản, theo thiết kế, sẽ luôn thành công:

[AlertWindow presentAlertWithTitle:@"My title" message:@"My message"];

1

Đáng buồn thay, giải pháp được chấp nhận đã không làm việc cho trường hợp của tôi. Tôi đã cố điều hướng đến một Trình điều khiển xem mới ngay sau khi thư giãn từ một Trình điều khiển xem khác.

Tôi tìm thấy một giải pháp bằng cách sử dụng một lá cờ để chỉ ra segue thư giãn nào được gọi.

@IBAction func unwindFromAuthenticationWithSegue(segue: UIStoryboardSegue) {
    self.shouldSegueToMainTabBar = true
}

@IBAction func unwindFromForgetPasswordWithSegue(segue: UIStoryboardSegue) {
    self.shouldSegueToLogin = true
}

Sau đó trình bày các VC muốn với present(_ viewControllerToPresent: UIViewController)

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    if self.shouldSegueToMainTabBar {
        let mainTabBarController = storyboard.instantiateViewController(withIdentifier: "mainTabBarVC") as! MainTabBarController
        self.present(mainTabBarController, animated: true)
        self.shouldSegueToMainTabBar = false
    }
    if self.shouldSegueToLogin {
        let loginController = storyboard.instantiateViewController(withIdentifier: "loginVC") as! LogInViewController
        self.present(loginController, animated: true)
        self.shouldSegueToLogin = false
    }
}

Về cơ bản, đoạn mã trên sẽ cho phép tôi bắt đầu thư giãn từ đăng nhập / Đăng ký VC và điều hướng đến bảng điều khiển hoặc bắt hành động thư giãn từ quên mật khẩu VC và điều hướng đến trang đăng nhập.


1

Tôi đã sửa lỗi này bằng cách lưu trữ hầu hết các trình điều khiển chế độ xem hàng đầu vào hằng số được tìm thấy trong khi chuyển qua rootViewControll:

if var topController = UIApplication.shared.keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }
    topController.present(controller, animated: false, completion: nil)
    // topController should now be your topmost view controller
}

1

Tôi thấy lỗi này xuất hiện sau khi cập nhật Xcode, tôi tin vào Swift 5 . Vấn đề đã xảy ra khi tôi lập trình khởi động một segue trực tiếp sau khi mở bộ điều khiển xem.

Giải pháp đã đến trong khi sửa một lỗi liên quan, đó là giờ đây người dùng đã có thể thư giãn các phân biệt bằng cách vuốt xuống trang. Điều này đã phá vỡ logic của chương trình của tôi.

Nó đã được sửa bằng cách thay đổi chế độ Trình bày trên tất cả các bộ điều khiển xem từ Tự động sang Toàn màn hình .

Bạn có thể làm điều đó trong bảng thuộc tính trong trình xây dựng giao diện. Hoặc xem câu trả lời này để biết cách thực hiện theo chương trình.


0

Tôi cũng có vấn đề này, nhưng nó không liên quan gì đến thời gian. Tôi đã sử dụng một singleton để xử lý các cảnh và tôi đặt nó làm người dẫn chương trình. Nói cách khác, "Tự" không được nối với bất cứ điều gì. Tôi chỉ thực hiện "cảnh" bên trong của nó là người dẫn chương trình mới và voila, nó đã hoạt động. (Voila mất liên lạc sau khi bạn tìm hiểu ý nghĩa của nó, heh).

Vì vậy, vâng, đó không phải là "kỳ diệu tìm đúng cách", mà là về việc hiểu mã của bạn đứng ở đâu và làm gì. Tôi rất vui khi Apple đưa ra một thông điệp cảnh báo bằng tiếng Anh đơn giản như vậy, ngay cả với cảm xúc với nó. Kudos cho nhà phát triển táo đã làm điều đó !!


0

Nếu một số giải pháp khác có vẻ không tốt vì một số lý do, bạn vẫn có thể sử dụng cách workaroundtrình bày cũ này với độ trễ bằng 0, như thế này:

dispatch_after(0, dispatch_get_main_queue(), ^{
    finishViewController *finished = [self.storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];
    [self presentViewController:finished animated:NO completion:NULL];    
});

Mặc dù tôi không thấy tài liệu nào đảm bảo rằng VC của bạn sẽ nằm trong hệ thống phân cấp chế độ xem trên khối công văn thời gian được lên lịch để thực hiện, tôi đã quan sát thấy nó sẽ hoạt động tốt.

Sử dụng độ trễ ví dụ 0,2 giây cũng là một tùy chọn. Và điều tốt nhất - theo cách này bạn không cần phải làm phiền với biến boolean trongviewDidAppear:


2
Mặc dù điều này có thể hoạt động ngay bây giờ, không có gì đảm bảo rằng Apple sẽ thay đổi hành vi và phá vỡ điều này với bạn trong tương lai. Sau đó, khi bạn quay lại để xem mã của mình để thử và sửa chữa mọi thứ một lần nữa, bạn sẽ tự hỏi tại sao bạn lại thực hiện công việc dường như không cần thiết này.
Cruinh

Công văn với 0 lần đã giúp tôi tiết kiệm khá nhiều lần - đôi khi những thứ chỉ nên hoạt động một cách hợp lý thì không hoạt động bình thường nếu không có nó. Vì vậy, chỉ cần đưa ra nhận xét cho bản thân và những người khác về lý do tại sao bạn làm những điều không rõ ràng (không chỉ là một công văn như vậy) và bạn sẽ ổn.
Dannie P

2
Bạn chỉ đang hack xung quanh vấn đề và không giải quyết nó.
Michael Peterson

0

Điều này hoạt động để trình bày bất kỳ bộ điều khiển xem, nếu bạn có sẵn bộ điều khiển điều hướng. self.navestionControll? .present (MyViewControll, hoạt hình: true, hoàn thành: nil) Ngoài ra, tôi cũng có thể trình bày các cảnh báo và trình điều khiển thư.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.