web-dev-qa-db-fra.com

Erreur UITableViewAlertForLayoutOutsideViewHierarchy: avertissement une seule fois (iOS 13 GM)

Je reçois une étrange erreur avec iOS13 lors de l'exécution d'une séquence et je ne peux pas comprendre ce que cela signifie, ni trouver de documentation pour cette erreur. Le problème est que cela semble causer beaucoup de retard (quelques secondes) jusqu'à ce que la séquence soit effectuée.

2019-09-11 22: 45: 38.861982 + 0100 Thrive [2324: 414597] [TableView] Avertissement une seule fois: UITableView a été invité à disposer ses cellules visibles et autres contenus sans être dans la hiérarchie des vues (la vue de table ou l'une de ses vues) superviews n'a pas été ajouté à une fenêtre). Cela peut provoquer des bogues en forçant les vues à l'intérieur de la vue de table à charger et à exécuter la mise en page sans informations précises (par exemple, les limites de la vue de table, la collection de traits, les marges de mise en page, les encarts de zone de sécurité, etc.), et entraînera également des frais généraux de performances inutiles en raison de passes de mise en page supplémentaires . Créez un point d'arrêt symbolique à UITableViewAlertForLayoutOutsideViewHierarchy pour intercepter cela dans le débogueur et voir ce qui a provoqué cela, afin que vous puissiez éviter cette action si possible, ou la reporter jusqu'à ce que la vue de table ait été ajoutée à une fenêtre. Vue de tableau: ; couche =; contentOffset: {0, 0}; contentSize: {315, 118}; adjustContentInset: {0, 0, 0, 0}; dataSource:>

J'utilise Hero mais j'ai essayé de le désactiver et d'utiliser une séquence régulière et cela n'a pas arrêté le décalage.

Le code pour lancer la séquence est didSelectRowAt

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if indexPath.section == 0 {
            selectedCell = realIndexFor(activeGoalAt: indexPath)
            performSegue(withIdentifier: "toGoalDetails", sender: nil)
        } else if indexPath.section == 1 {
            selectedCell = indexPath.row
            performSegue(withIdentifier: "toIdeaDetails", sender: nil)
        } else {
            selectedDecision = indexPath.row
            hero(destination: "DecisionDetails", type: .zoom)
        }
    }

Et puis aucun du code dans viewDidLoad ou viewWillAppear de la destination VC n'affecte cela en aucune façon (j'ai essayé de tout commenter sans aucune différence.

Une idée de ce qui cause ça? Je peux partager tous les autres détails nécessaires.

Je vous remercie.

17
CristianMoisei

Cela m'est arrivé parce que j'ai enregistré le périphérique pour la notification d'orientation de changement dans la méthode viewWillAppear (:). J'ai déplacé l'enregistrement dans viewDidAppear ( :) et Xcode ne s'arrête plus au point d'arrêt.

Ce que je peux dire, c'est que les changements de disposition peuvent être exécutés lorsque la vue est déjà visible ...

9
Miniapps

iPadOS 13.2.3 Swift 5.2 Xcode 11.2.1

Je viens de rencontrer ce problème uniquement lors du démarrage de l'application alors que l'appareil était en mode paysage. J'appelais la séquence de détails dans la fonction viewDidLoad du contrôleur maître pour m'assurer que la vue détaillée était correctement configurée.

     override func viewDidLoad() {
       super.viewDidLoad()
            ...
       self.performSegue(withIdentifier: "showDetail", sender: self)
     }

Lorsque j'ai supprimé le performSeque l'avertissement n'apparaissait plus, cependant, les boutons de la barre de gauche sur le contrôleur de détail ne fonctionnaient plus correctement, à nouveau uniquement lors du démarrage de l'application alors que l'appareil était en mode paysage. Le bouton le plus à gauche activerait le bouton suivant à droite au lieu de ce que le premier bouton était censé faire.

Le correctif pour les boutons de la barre était d'ajouter à viewDidLoad

     override func viewDidLoad() {
       super.viewDidLoad()
            ...
       self.splitViewController?.preferredDisplayMode = UISplitViewController.DisplayMode.allVisible
     }

Ensuite, exécutez

     override func viewWillAppear(_ animated: Bool) {
       self.splitViewController?.preferredDisplayMode = UISplitViewController.DisplayMode.automatic
       super.viewWillAppear(animated)
     }

Je n'ai aucune explication pourquoi cela a fonctionné!

Cette application avait parfaitement fonctionné jusqu'à ce que l'iPados 13 soit chargé.

2
Daryl1109

Je suis nouveau sur Xcode/Swift, cela peut ou non aider quelqu'un. J'ai commencé à obtenir cette erreur après la mise à jour vers iOS 13 et Xcode 11 dans l'application en revenant à une liste à partir d'une vue détaillée.

J'ai trouvé que je faisais un tableView.reloadRows Et tableView.insertRows Dans le déroulement (comme suggéré par Apple in l'un de leurs tutoriels )

@IBAction func unwindToMealList(sender: UIStoryboardSegue) {
    if let sourceViewController = sender.source as? MealViewController, let meal = sourceViewController.meal {

        if let selectedIndexPath = tableView.indexPathForSelectedRow {
            // Update an existing meal.
            meals[selectedIndexPath.row] = meal
            tableView.reloadRows(at: [selectedIndexPath], with: .none)
        }
        else {
            // Add a new meal.
            let newIndexPath = IndexPath(row: meals.count, section: 0)

            meals.append(meal)
            tableView.insertRows(at: [newIndexPath], with: .automatic)
        }
    }
}

)

J'ai commenté cette section de code et elle a disparu.

Curieusement, laisser le tri et self.tableView.reloadData() ne m'a pas donné l'erreur.

2
Joe H.

Comme @ joe-h, j'obtenais cette erreur et j'ai également été surpris car l'approche de déroulement qu'il montre ci-dessus est celle utilisée par de nombreux développeurs + est dans certains Apple exemple de code iOS iOS).

La ligne de déclenchement dans mon code (@ joe-h, je suppose que c'est probablement la vôtre aussi) est une tableView.reloadRows au selectedIndexPath (qui est une tableView.indexPathForSelectedRow non emballée):

tableView.reloadRows(at: [selectedIndexPath], with: .automatic)

Malheureusement, commenter la ligne n'est pas une option si vous vous déroulez après avoir mis à jour la valeur dans une ligne tableView existante (qui est une approche dans le tutoriel Apple FoodTracker mentionné ci-dessus, ainsi que celui utilisé) dans la série Tout le monde peut coder d'Apple). Si vous ne rechargez pas la ou les lignes, votre modification ne s'affichera pas dans la tableView. Après avoir commenté le rechargement lors du déroulement, j'ai ajouté un viewDidAppear avec le code suivant et cela semble réparer les choses:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    if let selectedIndexPath = tableView.indexPathForSelectedRow {
        tableView.reloadRows(at: [selectedIndexPath], with: .automatic)
    }
}

Je serais ravi de savoir si cette approche est saine, mais pour l'instant, cela semble fonctionner.

2
Gallaugher
extension UIView {

  func rootView() -> UIView {
     var view = self
     while view.superview.isNotNil {
         view = view.superview!
     }
     return view
  }

  var isOnWindow: Bool {
     return self.rootView() is UIWindow
    }
  }

alors il vous suffit de vérifier si votre tableView isOnWindow aime ...

if self.tableView.isOnWindow {
/// do stuff
}

Avis de non-responsabilité: comme l'explique la documentation, vous devrez peut-être reporter l'appel, ce qui signifie qu'il n'y a aucune garantie que votre méthode sera rappelée, il est donc de votre responsabilité d'effectuer votre mise à jour lorsque isOnWindow est vrai.

1
James Rochabrun

J'obtiens un point d'arrêt similaire avec SwiftUI, sans même traiter avec viewDidLoad ou viewDidappear

    //
//  ContentView.Swift
//  DD
//
//  Created by Roman Emperor on 3/29/20.
//  Copyright © 2020 Emperors. All rights reserved.
//
import Combine
import SwiftUI

// Defining a class Booking of type Bindable Object [changed to ObservableObject]
class Booking: ObservableObject {
    var didChange = PassthroughSubject<Void, Never>()

    // Array of types to work with
    static let types = ["Consultation", "Tooth Pain", "Cleaning", "Brases", "Dental Implant" ]
    // Setting instance varibale type
    var type = 0 { didSet { update() } }

    func update () {
        didChange.send(())
    }
}


struct ContentView: View {
    @ObservedObject var booking = Booking() //bindableObject in old Swift version

    var body: some View {
        NavigationView {
            Form {
                Section {
                    Picker(selection: $booking.type, label: Text("Select a Booking Type")) {
                        ForEach(0 ..< Booking.types.count){
                            Text(Booking.types[$0]).tag($0)
                        }
                    }
                }
            }
        .navigationBarTitle(Text("Darpan Dental Home"))
        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Le journal de sortie complet est ici:

*> 2020-03-29 09: 22: 09.626082 + 0545 DD [1840: 76404] [TableView] Avertissement

une seule fois: UITableView a été invité à disposer ses cellules visibles et autres contenus sans être dans la hiérarchie des vues (t la vue de table ou l'un de ses superviews n'a pas été ajouté à une fenêtre). Cela peut entraîner des bogues en forçant les vues à l'intérieur de la vue de table à charger et à exécuter la mise en page sans informations précises (par exemple, les limites de la vue de table, la collection de traits, les marges de mise en page, les encarts de zone de sécurité, etc.), et entraîneront également des frais généraux de performance inutiles dus à des mises en page supplémentaires. Créez un point d'arrêt symbolique à UITableViewAlertForLayoutOutsideViewHierarchy pour attraper cela dans le débogueur et voir ce qui a causé cela, afin que vous puissiez éviter cette action complètement si possible, ou la reporter jusqu'à ce que la vue de table ait été ajoutée à une fenêtre . *

** où est cette UITableViewAlertForLayoutOutsideViewHierarchy dans SwiftUI? **

0
Parajuli Roman