0

De temps en temps, je reçois des erreurs comme:Comment éviter les erreurs de tentative de présentation d'un contrôleur sur un contrôleur déjà présent?

Warning: Attempt to present <Controller3> on <Controller1> which is already presenting <Controller2> 

Je comprends que le prochain contrôleur doit être présenté sur le contrôleur qui est en haut de la pile (Controller2), pas un contrôleur quelque part ci-dessous (Régulateur1). Au lieu de corriger ces erreurs ponctuelles, comment concevoir notre application pour éviter ce problème une fois pour toutes?

Répondre

0

Une solution propre à ce problème est un contrôleur de navigation.

Si vous ne pouvez pas ou ne voulez pas utiliser un, vous pouvez facilement simuler sur un contrôleur de la vue normale:

extension UIViewController { 
    var topViewController: UIViewController { 
    return presentedViewController == nil ? self : presentedViewController!.topViewController 
    } 

    // If the topmost view controller is an instance of one of the given classes, it's popped. 
    // Then, the given view controller, if any, if pushed. 
    // 
    // This function can be called on any of the view controllers in the stack. 
    func pop(ifOneOf: [AnyClass], thenPush: UIViewController? = nil) { 
    if topViewController.presentingViewController != nil && topViewController.isKindOfOneOf(ifOneOf) { 
     topViewController.dismiss(animated: false, completion: { 
     self.pop(ifOneOf: [], thenPush: thenPush) 
     }) 
     return 
    } 
    if thenPush != nil { 
     push(thenPush!) 
    } 
    } 

    // Pushes the given view controller onto the stack. 
    // 
    // This method can be called on any of the view controllers in the stack. 
    func push(_ child: UIViewController) { 
    topViewController.present(child, animated: true) 
    } 
} 

extension NSObjectProtocol { 
    func isKindOfOneOf(_ classes: [AnyClass]) -> Bool { 
    for clazz in classes { 
     if isKind(of: clazz) { 
     return true 
     } 
    } 
    return false 
    } 
} 

Comme vous pouvez le voir, cela donne push() et pop() , similaire à un contrôleur de navigation. En outre, vous pouvez appeler ces méthodes sur n'importe quel contrôleur de la pile et les rediriger automatiquement vers le contrôleur le plus élevé, ce qui évite l'erreur dans la question.

Cette extension résout également le problème que si vous voulez supprimer un contrôleur et en présenter un autre, vous devez présenter uniquement dans le bloc d'achèvement, même si vous le rejetez sans animation. Sinon, vous obtiendrez la même erreur que ci-dessus. Cette extension corrige tous ces problèmes.