如何使用CoreData保存下载的CoreML模型?

时间:2019-08-07 06:39:07

标签: swift alamofire coreml alamofireobjectmapper

我已使用以下代码从python后端下载了新的经过训练的模型:

    import Foundation
    import Alamofire
    import AlamofireObjectMapper
    import ObjectMapper
    import CoreML

    class func downloadModel(modelUrl: String) {

        let destenation = Support.getDestenationForModel(modelUrl: modelUrl)

        AF.download(modelUrl, to: destenation).downloadProgress { progress in
            print("Download Progress: \(progress.fractionCompleted)")
        }
            .response { response in
                switch response.result {
                case .success(let success):
                    if let url = success?.absoluteURL {
                        FTApi.compileNewModel(url: url)
                    }
                    break
                case .failure(let err):
                    print(err)
                    break
                }
        }
    }

Support类中,getDestenationForModel如下:

    class func getDestenationForModel(modelUrl: String) -> DownloadRequest.Destination {
        let destenation: DownloadRequest.Destination =  { url, options in
            guard let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first ,
                let modelUrl = URL(string: modelUrl) else {
                    preconditionFailure("unable to use documents directory")
            }

            let fileURL = documentsURL.appendingPathComponent(modelUrl.lastPathComponent)

            AppPrefrences.pathOfModel = modelUrl.lastPathComponent
            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
        }
        return destenation
    }

下载完成后,我尝试使用以下代码将模型保存到CoreData(我找不到其他方法,也许您可​​以推荐其他方法):

    private class func compileNewModel(url: URL) {
        do {
            let compiledUrl = try MLModel.compileModel(at: url)
            guard let model = try? MLModel(contentsOf: compiledUrl)
                else {
                    print("cannot get content of model")
                    return
            }

            let coreMlModel = CML(context: PersistanceService.context)
            print(type(of: model)) // => MLNeuralNetworkEngine
            coreMlModel.model = (model as NSObject)
            PersistanceService.saveContext() // here I have an error
        } catch {
            print("cannot download the model!")
        }
    }

错误是:*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MLNeuralNetworkEngine encodeWithCoder:]: unrecognized selector sent to instance 0x104d38280'

这是我的CoreData实体类:

import Foundation
import CoreData


extension CML {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<CML> {
        return NSFetchRequest<CML>(entityName: "CML")
    }

    @NSManaged public var model: NSObject?

}

我尝试将类型从NSObject更改为MLModel,但是结果是相同的。

1 个答案:

答案 0 :(得分:1)

您为什么还要尝试这个?这不是CoreData设计的目的。

正确的解决方案是将文件夹从ConstructedURL复制到应用程序的“应用程序支持”文件夹中的某个位置。然后,当您创建MLModel对象时,请使用“应用程序支持”文件夹中的URL。

阅读Core ML文档中的“在用户设备上下载和编译模型”以了解如何执行此操作。