简体   繁体   English

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

[英]Swift UIApplication.delegate must be used from main thread only

Xcode is complaining when I try to set the appDelegate & context variables, required in order to use CoreData.当我尝试设置使用 CoreData 所需的 appDelegate 和上下文变量时,Xcode 抱怨。

Essentially, I would like to store the results of my Vision / CoreML image classification request into a Core Data database for offline analysis.本质上,我想将我的 Vision / CoreML 图像分类请求的结果存储到 Core Data 数据库中以进行离线分析。

Seen related threads to this, and tried a bunch.看到了与此相关的线程,并尝试了一堆。 Problem does not go away, and now (unknown to me!) the CoreData save errors after few hundred records.问题并没有消失,现在(我不知道!)CoreData 在几百条记录后保存错误。 I am hoping removing this issue altogether will solve the error problem or I can troubleshoot it later...我希望完全删除此问题将解决错误问题,或者我可以稍后对其进行故障排除...

This is specifically for debugging, and won't likely need CoreData when data analyses has finished.这专门用于调试,并且在数据分析完成后可能不需要 CoreData。

Tried putting the variable declarations right at the top of the ViewController class, with appending "!"尝试将变量声明放在 ViewController 类的顶部,并附加“!” as I know I will be setting them later.我知道我稍后会设置它们。 Tried putting the 2 lines in a DispatchQueue.main.async closure.尝试将 2 行放入 DispatchQueue.main.async 闭包中。

Tried wrapping these 2 lines inside a "DispatchQueue.main.async({ })" line, but then I can no longer reference the context on the "newItem" lines.尝试将这两行包装在“DispatchQueue.main.async({})”行中,但随后我无法再引用“newItem”行上的上下文。 Wrapping the whole section does not work either, probably as the CoreData cannot see / access the data within the image request(?)包装整个部分也不起作用,可能是因为 CoreData 无法查看/访问图像请求中的数据(?)

The code:编码:

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

This is an annoying warning;这是一个烦人的警告; however, it seems to be there for a reason as iOS wants to avoid deadlocks(???).然而,它的存在似乎是有原因的,因为 iOS 想要避免死锁(???)。

Using Swift 3, here's what I've found is a safe way to manage Core Data + AppDelegate (your mileage may vary):使用 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

Hope this helps!希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 UIApplication 委托只能在主线程中使用 - Swift - UIApplication delegate must be used from main thread only - Swift UIApplication.registerForRemoteNotifications() 只能从主线程调用 - UIApplication.registerForRemoteNotifications() must be called from main thread only Swift-stopAnimating()-必须仅在主线程中使用 - Swift - stopAnimating() - must be used from main thread only 不使用UIApplication.delegate获取方向? - Getting orientation without using UIApplication.delegate? ImageView 只能在主线程中使用 - ImageView must be used from main thread only Swift错误“ UIButton.currentTitle必须仅在主线程中使用” - Swift Error “UIButton.currentTitle must be used from main thread only” Swift - 从主线程访问 UIApplication.shared.statusBarOrientation - Swift -access UIApplication.shared.statusBarOrientation from main thread UIViewController.navigationController 只能在主线程中使用 - UIViewController.navigationController must be used from main thread only iOS:只能从主线程使用UIWindow.rootViewController - iOS: UIWindow.rootViewController must be used from main thread only UIDatePicker setEnabled必须仅在主线程中使用 - UIDatePicker setEnabled must be used from main thread only
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM