Xcode UIView.init(frame :)只能在主线程中使用

时间:2017-09-22 10:33:47

标签: ios swift xcode multithreading uikit

我正在尝试在后台线程中渲染一些视图,以免影响主线程。在Xcode 9之前,这从来都不是问题。

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

UIView.init(frame :)必须仅在主线程中使用

第二行发生此错误。

更新

Apple UIView文档实际上在线程注意事项部分中说明了:

  

必须在主线程上对应用程序的用户界面进行操作。因此,您应该始终从应用程序主线程中运行的代码调用UIView类的方法。 这可能不是绝对必要的唯一时间是创建视图对象本身,但所有其他操作应该在主线程上发生。

3 个答案:

答案 0 :(得分:25)

Xcode 9有一个新的运行时 Main Thread Checker ,用于检测后台线程对UIKit的调用并生成警告。

我知道它的意思是生成警告并且不会使应用程序崩溃,但您可以尝试为您的测试目标禁用主线程检查器。

enter image description here

我在一个示例项目中尝试了这个代码,调试器在问题上暂停(正如它应该的那样),但应用程序没有崩溃。

override func viewDidLoad() {
    super.viewDidLoad()

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

答案 1 :(得分:15)

您可以使用此功能

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)

答案 2 :(得分:2)

  DispatchQueue.main.async { 
     // UIView usage
  }