Swift UIApplication.delegate 只能在主线程中使用

Posted

技术标签:

【中文标题】Swift UIApplication.delegate 只能在主线程中使用【英文标题】:Swift UIApplication.delegate must be used from main thread only 【发布时间】:2017-12-02 22:37:39 【问题描述】:

当我尝试设置 appDelegate 和上下文变量时,XCode 抱怨,这是使用 CoreData 所必需的。

基本上,我想将我的 Vision / CoreML 图像分类请求的结果存储到 Core Data 数据库中以供离线分析。

看到了与此相关的线程,并尝试了一堆。问题并没有消失,现在(我不知道!)CoreData 在几百条记录后保存错误。我希望完全删除此问题将解决错误问题,或者我可以稍后对其进行故障排除...

这是专门用于调试的,数据分析完成后可能不需要 CoreData。

尝试将变量声明放在 ViewController 类的顶部,并附加“!”我知道我稍后会设置它们。尝试将 2 行放入 DispatchQueue.main.async 闭包中。

尝试将这两行包装在“DispatchQueue.main.async( )”行中,但随后我无法再引用“newItem”行上的上下文。包装整个部分也不起作用,可能是因为 CoreData 无法查看/访问图像请求中的数据(?)

代码:

func processCameraBuffer(sampleBuffer: CMSampleBuffer) 

    let coreMLModel = Inceptionv3()

    if let model = try? VNCoreMLModel(for: coreMLModel.model) 
        let request = VNCoreMLRequest(model: model, completionHandler:  (request, error) in
            if let results = request.results as? [VNClassificationObservation] 
                var counter = 1

                for classification in results 

                        let timestamp = NSDate().timeIntervalSince1970

                    // Purple Error is here
                    let appDelegate = UIApplication.shared.delegate as! AppDelegate
                    let context = appDelegate.persistentContainer.viewContext

                    let newItem = NSEntityDescription.insertNewObject(forEntityName: "Predictions", into: context)
                        newItem.setValue(classification.confidence, forKey: "confidence")
                        newItem.setValue(classification.identifier, forKey: "identifier")
                        newItem.setValue(counter, forKey: "index")
                        newItem.setValue(timestamp, forKey: "timestamp")
                        newItem.setValue("inceptionv3", forKey: "mlmodel")
                        print("counter: \(counter) \(classification.identifier)")
                        do 
                            try context.save()
                         catch 
                            print("CoreData Save error")
                            print(error.localizedDescription)
                        
                    counter += 1
                
            
        )

            if let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) 
                let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])
                do 
                    try handler.perform([request])
                 catch 
                    print(error.localizedDescription)
                
            
    

【问题讨论】:

【参考方案1】:

这是一个烦人的警告;然而,它的存在似乎是有原因的,因为 ios 想要避免死锁(???)。

使用 Swift 3,我发现这是一种管理 Core Data + AppDelegate 的安全方法(您的里程可能会有所不同):

DispatchQueue.main.async 
    if let app = UIApplication.shared.delegate as? AppDelegate 
        app.managedObjectContext.performAndWait 
            // .. Core Data work here
            // .. context.save() 
         // app.managedObjectContext.performAndWait
     // if let app = UIApplication.shared.delegate as? AppDelegate
 // DispatchQueue.main.async

希望这会有所帮助!

【讨论】:

如果没有“UIApplication.delegate 只能从主线程使用”警告,我们就不能获取共享实例。

以上是关于Swift UIApplication.delegate 只能在主线程中使用的主要内容,如果未能解决你的问题,请参考以下文章

Swift入门系列--Swift官方文档(2.2)--中文翻译--About Swift 关于Swift

swift 示例BS swift.swift

swift swift_bug.swift

ios 整理(一)swift和oc的区别

swift swift_extension5.swift

swift swift_optional4.swift