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 只能在主线程中使用的主要内容,如果未能解决你的问题,请参考以下文章