web-dev-qa-db-ja.com

Xcode UIView.init(frame :)はメインスレッドからのみ使用する必要があります

メインスレッドに影響を与えないように、バックグラウンドスレッドでいくつかのビューをレンダリングしようとしています。それはXcode 9以前では決して問題ではありませんでした。

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

UIView.init(frame :)はメインスレッドからのみ使用する必要があります

このエラーは2行目で発生します。

更新

Apple UIViewドキュメンテーションは、実際にはThreading Considerationsセクションで述べています:

アプリケーションのユーザーインターフェースの操作は、メインスレッドで行う必要があります。したがって、アプリケーションのメインスレッドで実行されているコードからUIViewクラスのメソッドを常に呼び出す必要があります。 これが厳密に必要でない場合は、ビューオブジェクト自体を作成するときだけですが、他のすべての操作はメインスレッドで行う必要があります。

27

Xcode 9には、新しいランタイムメインスレッドチェッカーがあり、バックグラウンドスレッドからUIKitの呼び出しを検出して警告を生成します。

アプリをクラッシュさせるのではなく、警告を生成することを意図していますが、テストターゲットのメインスレッドチェッカーを無効にしてみてください。

enter image description here

サンプルプロジェクトでこのコードを試してみましたが、デバッガーは問題で一時停止しました(想定どおり)が、アプリはクラッシュしませんでした。

override func viewDidLoad() {
    super.viewDidLoad()

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

この機能を使用できます

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()
}

この機能の使用方法

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

メインスレッドエントリ

次のようにメインスレッドを入力できます

      DispatchQueue.main.async { 
         // UIView usage
      }

5
Aditya A.Rajan