web-dev-qa-db-fra.com

Xcode UIView.init (frame :) doit être utilisé à partir du thread principal uniquement

J'essaie de rendre certaines vues dans le fil de fond pour ne pas affecter le fil principal. Ce n'était jamais un problème avant Xcode 9.

DispatchQueue.global(qos: .background).async {
    let customView = UIView(frame: .zero)
    DispatchQueue.main.async {
        self.view.addSubview(customView)
    }
}

UIView.init (frame :) doit être utilisé à partir du thread principal uniquement

Cette erreur se produit dans la deuxième ligne.

Mise à jour

La documentation Apple UIView] indique en fait dans la section Considérations relatives au threading :

Les manipulations sur l'interface utilisateur de votre application doivent être effectuées sur le thread principal. Ainsi, vous devriez toujours appeler les méthodes de la classe UIView à partir du code exécuté dans le thread principal de votre application. La seule fois où cela peut ne pas être strictement nécessaire, c'est lors de la création de l'objet de vue lui-même, mais toutes les autres manipulations doivent avoir lieu sur le thread principal.

27
Lukas Würzburger

Xcode 9 a un nouveau runtime Vérificateur de thread principal qui détecte l'appel à UIKit à partir d'un thread en arrière-plan et génère des avertissements.

Je sais que son objectif est de générer des avertissements et de ne pas bloquer l'application, mais vous pouvez essayer de désactiver le vérificateur de thread principal pour votre cible de test.

enter image description here

J'ai essayé ce code dans un exemple de projet, le débogueur s'est arrêté sur le problème (comme il est supposé le faire), mais l'application ne s'est pas bloquée.

override func viewDidLoad() {
    super.viewDidLoad()

    DispatchQueue.global().async {
        let v = UIView(frame: .zero)
    }
}
25
Puneet Sharma

Vous pouvez utiliser cette fonction

func downloadImage(urlstr: String, imageView: UIImageView) {
    let url = URL(string: urlstr)!
    let task = URLSession.shared.dataTask(with: url) { data, _, _ in
        guard let data = data else { return }
        DispatchQueue.main.async { // Make sure you're on the main thread here
            imageview.image = UIImage(data: data)
        }
    }
    task.resume()
}

Comment utiliser cette fonction?

downloadImage(urlstr: "imageUrl", imageView: self.myImageView)
15
Erhan Demirci

Entrée du filetage principal

Vous pouvez entrer le fil principal comme suit

      DispatchQueue.main.async { 
         // UIView usage
      }

5
Aditya A.Rajan