2017-09-22 55 views
15

Próbuję renderować niektóre widoki w osobnym wątku, aby nie wpływać na główny wątek. To nigdy nie było problemem przed Xcode 9. Teraz moja jednostka testuje awarię tutaj.Xcode 9 [UIView initWithFrame:] musi być używany z głównego wątku tylko

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]; 
    ... 
} 

Dlaczego nie powinienem móc renderować elementów interfejsu do późniejszego wykorzystania w wątku innym niż główny wątek?

+0

byłem świadomy tej nowej reguły, ale zastanawiam się, jak wiele pracy nadal można odciążyć do wątku backgroudn ... –

Odpowiedz

14

XCode 9 ma nowy runtime Main Thread Checker, który wykrywa wywołanie UIKit z wątku tła i generuje ostrzeżenia.

Wiem, że ma on generować ostrzeżenia i nie powodować awarii aplikacji, ale możesz spróbować wyłączyć Główny sprawdzian wątków dla swojego celu testowego.

enter image description here

Próbowałem ten kod w projekcie próbki, debugger zatrzymał się przy numerze (jak to ma), ale aplikacja nie upaść.

override func viewDidLoad() { 
    super.viewDidLoad() 

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

Że zrobił to teraz. Dzięki! – lukwuerz

+0

W moim przypadku wywoływałem metodę z poziomu żądania URLSession. –

1

Można użyć tej funkcji

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

Jak korzystać z tej funkcji?

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