Swift Core Data Class方法?

时间:2018-06-20 14:03:23

标签: swift core-data

我目前正在学习Core Data,我有两个视图控制器,它们使用同一段代码来获取用户个人资料。问题是它是相同的代码复制和粘贴,我想避免这种情况。我正在使用托管类方法来访问数据,并且每个控制器都具有以下方法:

var profileHolder: Profile!
    let profileRequest = Profile.createFetchRequest()
    profileRequest.predicate = NSPredicate(format: "id == %d", 1)
    profileRequest.fetchLimit = 1
    if let profiles = try? context.fetch(profileRequest) {
        if profiles.count > 0 {
            profileHolder = profiles[0]
        }
    }

    if profileHolder == nil {
        let newProfile = Profile(context: context)
        newProfile.id = 1
        newProfile.attempts = nil
        profileHolder = newProfile
    }
    profile = profileHolder

配置文件是控制器内部的变量:var profile: Profile!,我在viewWillAppear()内部称上述内容

我知道有一种更简洁的方法,我想在课堂上讲这个逻辑,但是不确定如何做。

谢谢

3 个答案:

答案 0 :(得分:1)

java.lang.UnsatisfiedLinkError: dlopen failed: library "C:\MyProject\MyProject.Mobile\bin\Android\Debug\ARM\lib1.so" not found
at java.lang.Runtime.loadLibrary(Runtime.java:372)
....

profileHolder在这里是强制展开可选值。而且您要从核心数据中获取数据并在viewWillAppear中分配值,这很冒险,因为profileHolder为零,如果在viewWillAppear之前访问它,则可能触发崩溃。

我的建议是:

ViewTreeObserver vto = imageView.getViewTreeObserver();
    vto.addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
        @Override
        public void onDraw() {

            float[] f = new float[9];
            imageView.getImageMatrix().getValues(f);

            // Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
            final float scaleX = f[Matrix.MSCALE_X];
            final float scaleY = f[Matrix.MSCALE_Y];


            // Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
            final Drawable d = imageView. getDrawable();
            final int origW = d.getIntrinsicWidth();
            final int origH = d.getIntrinsicHeight();

            // Calculate the actual dimensions
            final int actW = Math.round(origW * scaleX);
            final int actH = Math.round(origH * scaleY);

        }
    });

这将确保在初始化视图控制器时获取或创建profileHolder。

但是,如果

则不起作用
 var profileHolder: Profile!

是viewController的存储属性,在这种情况下,请执行以下操作:

var profileHolder: Profile 
{
    if let profiles = try? context.fetch(profileRequest),
       profiles.count > 0           
    {
       return profiles[0]
    }
    else
    {
       let newProfile = Profile(context: context)
       newProfile.id = 1
       newProfile.attempts = nil
       return newProfile
    }
}()

答案 1 :(得分:0)

这是我为一个项目创建的结构,该结构使我可以在任何地方访问CoreData函数。创建一个新的空swift文件,然后执行以下操作。

import CoreData

// MARK: - CoreDataStack

struct CoreDataStack {

    // MARK: Properties

    private let model: NSManagedObjectModel
    internal let coordinator: NSPersistentStoreCoordinator
    private let modelURL: URL
    internal let dbURL: URL
    let context: NSManagedObjectContext
    let privateContext: NSManagedObjectContext

    // MARK: Initializers

    init?(modelName: String) {

        // Assumes the model is in the main bundle
        guard let modelURL = Bundle.main.url(forResource: modelName, withExtension: "momd") else {
            print("Unable to find \(modelName)in the main bundle")
            return nil
        }
        self.modelURL = modelURL

        // Try to create the model from the URL
        guard let model = NSManagedObjectModel(contentsOf: modelURL) else {
            print("unable to create a model from \(modelURL)")
            return nil
        }
        self.model = model

        // Create the store coordinator
        coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)

        // create a context and add connect it to the coordinator
        //context.persistentStoreCoordinator = coordinator

        privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
        privateContext.persistentStoreCoordinator = coordinator

        context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        context.parent = privateContext

        // Add a SQLite store located in the documents folder
        let fm = FileManager.default
        guard let docUrl = fm.urls(for: .documentDirectory, in: .userDomainMask).first else {
            print("Unable to reach the documents folder")
            return nil
        }

        self.dbURL = docUrl.appendingPathComponent("model.sqlite")

        // Options for migration
        let options = [NSInferMappingModelAutomaticallyOption: true,NSMigratePersistentStoresAutomaticallyOption: true]

        do {
            try addStoreCoordinator(NSSQLiteStoreType, configuration: nil, storeURL: dbURL, options: options as [NSObject : AnyObject]?)
        } catch {
            print("unable to add store at \(dbURL)")
        }
    }

    // MARK: Utils

    func addStoreCoordinator(_ storeType: String, configuration: String?, storeURL: URL, options : [NSObject:AnyObject]?) throws {
        try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: dbURL, options: nil)
    }
}

// MARK: - CoreDataStack (Removing Data)

internal extension CoreDataStack  {

    func dropAllData() throws {
        // delete all the objects in the db. This won't delete the files, it will
        // just leave empty tables.
        try coordinator.destroyPersistentStore(at: dbURL, ofType:NSSQLiteStoreType , options: nil)
        try addStoreCoordinator(NSSQLiteStoreType, configuration: nil, storeURL: dbURL, options: nil)
    }
}

// MARK: - CoreDataStack (Save Data)

extension CoreDataStack {

    func saveContext() throws {
        /*if context.hasChanges {
            try context.save()
        }*/
        if privateContext.hasChanges {
            try privateContext.save()
        }
    }

    func autoSave(_ delayInSeconds : Int) {

        if delayInSeconds > 0 {
            do {
                try saveContext()
                print("Autosaving")
            } catch {
                print("Error while autosaving")
            }

            let delayInNanoSeconds = UInt64(delayInSeconds) * NSEC_PER_SEC
            let time = DispatchTime.now() + Double(Int64(delayInNanoSeconds)) / Double(NSEC_PER_SEC)

            DispatchQueue.main.asyncAfter(deadline: time) {
                self.autoSave(delayInSeconds)
            }
        }
    }
}

答案 2 :(得分:0)

创建一个可以管理核心数据操作的类(CoreDataManager)。

import CoreData

class CoreDataManager:NSObject{
/// Application Document directory
lazy var applicationDocumentsDirectory: URL = {
    let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return urls[urls.count-1]
}()
/// Core data manager
static var shared = CoreDataManager()
/// Managed Object Model
lazy var managedObjectModel: NSManagedObjectModel = {

    let modelURL = Bundle.main.url(forResource: “your DB name”, withExtension: "momd")!
    return NSManagedObjectModel(contentsOf: modelURL)!
}()
/// Persistent Store Coordinator 
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
    var failureReason = "There was an error creating or loading the application's saved data."
    let options = [ NSInferMappingModelAutomaticallyOption : true,
                    NSMigratePersistentStoresAutomaticallyOption : true]
    do {
        try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: options)
        persistanceStoreKeeper.sharedInstance.persistanceStorePath = url
    } catch {
        var dict = [String: AnyObject]()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject
        dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject
        dict[NSUnderlyingErrorKey] = error as NSError
        let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
        abort()
    }
    return coordinator
}()
/// Managed Object Context
lazy var managedObjectContext: NSManagedObjectContext = {

    let coordinator = self.persistentStoreCoordinator
    var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext
}()
/// Save context
func saveContext () {
    if managedObjectContext.hasChanges {
        do {
            try managedObjectContext.save()
        } catch {
            let nserror = error as NSError
            NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
            abort()
        }
    }
}
}

在您的班级中添加波纹管功能。

func fetchProfile(profileId:String,fetchlimit:Int,completion: ((_ fetchedList:["Your model class"]) -> Void)){
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Your entity name")
    let predicate:NSPredicate = NSPredicate(format: "id = %@", profileId)
    fetchRequest.predicate=predicate
    fetchRequest.fetchLimit = fetchlimit
    do {
        let results =
            try CoreDataManager.shared.managedObjectContext.fetch(fetchRequest)
        let profileList:["Your model class"] = results as! ["Your model class"]
        if(profileList.count == 0){
            //Empty fetch list
        }
        else{
            completion(profileList)

        }
    }
    catch{
       //error
    }
}

根据您的要求替换“您的模型课程”。

您可以调用函数“ fetchProfile”,并将结果保存在完成块中。