2017-09-22 12 views
15

メインスレッドに影響しないように、別のスレッドでいくつかのビューをレンダリングしようとしています。これはXcode 9以前は問題ではありませんでした。ここで私のユニットテストがクラッシュします。Xcode 9 [UIView initWithFrame:]メインスレッドのみから使用する必要があります

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    UIImage *snapShot = [self generateShadowImage]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     imageView.image = snapShot; 
    }); 
}); 

... 

- (UIImage *)generateShadowImage { 

    // It crashes here: 
    UIView *shadowView = [[UIView alloc] initWithFrame:CGRectZero]; 
    ... 
} 

後でメインスレッド以外のスレッドで使用するためにUI要素をレンダリングできないのはなぜですか?

+0

私はこの新しい規則を知っていましたが、あなたはまだバックグラウンドのスレッドにオフロードできる作業がどれくらいかと思います... –

答えて

14

XCode 9には、バックグラウンドスレッドからUIKitへの呼び出しを検出し、警告を生成する新しいランタイムMain Thread Checkerがあります。

私は警告を生成し、アプリケーションをクラッシュさせないことを知っていますが、あなたのテストターゲットに対してメインスレッドチェッカーを無効にすることができます。

enter image description here

は、私は(それがすることになっているとして)サンプルプロジェクトでは、このコードは、デバッガが問題で一時停止しようとしたが、アプリがクラッシュしませんでした。

override func viewDidLoad() { 
    super.viewDidLoad() 

    DispatchQueue.global().async { 
     let v = UIView(frame: .zero) 
    } 
} 
+1

これは今のところそれでした。ありがとう! – lukwuerz

+0

私の場合、URLSessionリクエストからメソッドを呼び出していました。 –

1

あなたはこの機能を使用する方法

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

この機能を使用することができますか?

関連する問題