swift中使用core data

chenshipeng發表於2017-12-17

在建立了.xcdatamodeld檔案之後,需要建立相關的model,之後便是初始化CoreData。一般使用的是NSManagedObjectModel、NSManagedObjectContext、NSPersistentStoreCoordinator。 swift中建立單例:

static let shared:CoreDataManager = {
    
        let instance = CoreDataManager()
        return instance
    }()
複製程式碼

首先,建立model: 根據檔名字來建立model: //建立model物件,model需要momd

var managedObjectModel:NSManagedObjectModel{
    
        if !(_managedObjectModel != nil){
        
            let modelURL = Bundle.main.url(forResource: dataModelName, withExtension: "momd")
            _managedObjectModel = NSManagedObjectModel(contentsOf: modelURL!)
        }
        
        return _managedObjectModel!
    }
複製程式碼

之後是建立coordinator: 根據Model建立coordinator: //初始化coordinator,需要model

 var persistentStoreCoordinator:NSPersistentStoreCoordinator{
    
        if !(_persistentStoreCoordinator != nil) {
            let storeURL = self.applicationDocumentsDirectory.appendingPathComponent(storeName)
            _persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
            
            do{
            
                //sqlite樣式的儲存
                try _persistentStoreCoordinator!.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: self.databaseOptions())
            }catch _ as NSError{
            
                abort()
            }
        }
        return _persistentStoreCoordinator!
    }
複製程式碼

最後是建立Context: 需要使用coordinator建立Context: //context初始化

var managedObjectContext:NSManagedObjectContext{
    
        //建立context,context需要coordinator
        if Thread.isMainThread{
            if !(_managedObjectContext != nil){

                let coordinator = self.persistentStoreCoordinator
                if coordinator != NSNull(){
                
                    //主佇列的context
                    _managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
                    _managedObjectContext!.persistentStoreCoordinator = coordinator
                }
                return _managedObjectContext!


            }
        
            
        }else{
        
            var threadContext:NSManagedObjectContext? = Thread.current.threadDictionary["NSManagedObjectContext"] as? NSManagedObjectContext
            if threadContext == nil {
                //非主佇列的context
                threadContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
                //設定parent
                threadContext!.parent = _managedObjectContext
                //設定name
                threadContext!.name = Thread.current.description
                Thread.current.threadDictionary["NSManagedObjectContext"] = threadContext
                NotificationCenter.default.addObserver(self, selector: #selector(CoreDataManager.contextWillSave(_:)), name: NSNotification.Name.NSManagedObjectContextWillSave, object: threadContext)
            }else{
            
                print("using old context")
                
            }
            return threadContext!
            
        }
        
        return _managedObjectContext!
    }
複製程式碼

對於CoreData中資料的處理,有刪除和修改,新增,更新,查詢等: 查詢:

func executeFetchRequest(_ request:NSFetchRequest<NSFetchRequestResult>) -> Array<NSFetchRequestResult>? {
        var results:Array<NSFetchRequestResult>?
        self.managedObjectContext.performAndWait {
            var fetchError:NSError?
            do{
            
                results = try self.managedObjectContext.fetch(request)
            }catch let error as NSError{
            
                fetchError = error
                results = nil
            }catch {
            
                fatalError()
            };
            if let error = fetchError{
            
                print("Warning!! \(error.description)")
            }
        }
        
        return results
    }
複製程式碼

或者帶回撥的查詢:

func executeFetchRequest(_ request:NSFetchRequest<NSFetchRequestResult>,completionHanlder:@escaping (_ results:Array<NSFetchRequestResult>?) -> Void) {
        self.managedObjectContext.perform(){
        
            var fetchError:NSError?
            var results:Array<NSFetchRequestResult>?
            do{
            
                results = try self.managedObjectContext.fetch(request)
            }catch let error as NSError{
            
                fetchError = error
                results = nil
            }catch{
            
                fatalError()
            }
            if let error = fetchError {
            
                print("Warning!! \(error.description)")
            }
            completionHanlder(results)
        }
    }
複製程式碼

儲存資料:

func save() {
        let context:NSManagedObjectContext = self.managedObjectContext
        if context.hasChanges{
        
            context.perform {
                var saveError:NSError?
                let saved:Bool
                do{
                
                    try context.save()
                    saved = true
                }catch let error as NSError{
                
                    saveError = error
                    saved = false
                }catch {
                
                    fatalError()
                };
                if !saved{
                
                    if let error = saveError{
                    
                        print("Warning!! Saving error \(error.description)")
                    }
                }
                
                if context.parent != nil{
                
                    context.parent!.performAndWait {
                        var saveError:NSError?
                        let saved:Bool
                        do{
                        
                            try context.parent!.save()
                            saved = true
                        }catch let error as NSError{
                        
                            saveError = error
                            saved = false
                        }catch {
                        
                            fatalError()
                        }
                        if !saved{
                        
                            if let error = saveError{
                            
                                print("Warning!! Saving parent error \(error.description)")
                            }
                        }
                    }
                }
                
            }
        }
    }
複製程式碼

context儲存時:

func contextWillSave(_ notification:Notification) {
        let context:NSManagedObjectContext! = notification.object as! NSManagedObjectContext
        let insertedObjects:NSSet = context.insertedObjects as NSSet
        
        if insertedObjects.count != 0 {
            var obtainError:NSError?
            
            do{
            
                try context.obtainPermanentIDs(for: insertedObjects.allObjects as! [NSManagedObject])
            }catch let error as NSError{
            
                obtainError = error
            }
            if let error = obtainError{
            
                print("Warnning!! obtain ids error \(error.description)")
            }
            
            
        }
    }
複製程式碼

刪除某一個model的資料:

func deleteEntity(_ object:NSManagedObject) {
        object.managedObjectContext?.delete(object)
    }
    
    func deleteTable<ResultType:NSFetchRequestResult>(request:NSFetchRequest<ResultType>,tableName:String) {
        let managedObjectContext = self.managedObjectContext
        let entity = NSEntityDescription.entity(forEntityName: tableName, in: managedObjectContext)
        let request = NSFetchRequest<NSFetchRequestResult>()
        request.includesPropertyValues = false
        request.entity = entity
        
        
        let items = self.executeFetchRequest(request)
        if (items != nil  && items!.count > 0){
        
            for obj in items! {
            
                let item = obj as! NSManagedObject
                self.deleteEntity(item)
            }
            
            self.save()
        }
    }
複製程式碼

以上是對CoreData的初始化,在具體到某一個Model的時候,需要再進行封裝: 有資料轉化(獲取的資料轉成對應的model)、獲取資料、儲存資料,新增資料,刪除資料等;需要用到剛才初始化的CoreDataManager:

import Foundation
import CoreData
import SwiftyJSON
class ArticleDal: NSObject {
    
    
    func addList(_ items:[AnyObject]) {
        for po in items{
        
            self.addArticle(po,save:false)
        }
        CoreDataManager.shared.save()
    }
    
    func addArticle(_ obj:AnyObject,save:Bool) {
        let context = CoreDataManager.shared.managedObjectContext
        let model = NSEntityDescription.entity(forEntityName: "Article", in: context)
        let article = Article(entity: model!, insertInto: context)
        if model != nil{
        
            self.obj2ManagedObject(obj,article:article)
            if save {
            
                CoreDataManager.shared.save()
            }
        }
    }
    
    func deleteAll() {
        CoreDataManager.shared.deleteTable(request: NSFetchRequest<Article>(), tableName: "Article")
    }
    func save() {
        let context = CoreDataManager.shared.managedObjectContext
        do{
        
            try context.save()
        }catch _{
        
        }
    }
    
    func getList() -> [AnyObject]? {
        let request:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Article")
        let sort1 = NSSortDescriptor(key: "articleId", ascending: false)
        
        request.fetchLimit = 30
        request.sortDescriptors = [sort1]
        request.resultType = .dictionaryResultType
        let result = CoreDataManager.shared.executeFetchRequest(request)
        
        return result
    }
    
    func obj2ManagedObject(_ obj:AnyObject,article:Article) {
        var data =  JSON(obj)
        let articleId = data["articleId"].int64!
        let title = data["title"].string!
        let content = data["content"].string
        let createDate = data["createDate"].int64!
        let viewCount = data["viewCount"].int64!
        let siteId = data["siteId"].int64!
        let sourceName = data["sourceName"].string
        let sourceUrl = data["sourceUrl"].string
        let author = data["author"].string
        let language = data["language"].string
        let imageUrl = data["imageUrl"].string
        
        article.articleId = articleId
        article.title = title;
        article.content = content;
        article.createDate = createDate
        article.siteId = siteId
        article.sourceName = sourceName
        article.viewCount = viewCount
        article.sourceUrl = sourceUrl
        article.author = author
        article.language = language
        article.imageUrl = imageUrl
    }
}
複製程式碼

相關文章