以前寫過一篇介紹iOS數據存儲方法的文章,包含:FMDB,SQLite3 ,Core Data,Plist,偏好設置,歸檔。 連接:www.jianshu.com/p/e88880be7…git
本文則是介紹Swift中CoreData的基本使用。
文中示例代碼GitHub地址:Demogithub
1、 圖形化建立模型
2、 手動建立模型並實現AppDelegate中的代碼
3、 建立並實現CoreDataManagersql
建立項目的時候,勾選下圖中的Use Core Data選項,工程中會自動建立一個數據模型文件。固然,你也能夠在開發中本身手動建立。編程
下圖就是自動建立出來的文件swift
若是沒有勾選,也能夠在這裏手動建立。數組
點擊Add Entity以後,至關一張數據表。表的名稱本身在上方定義,注意首字母要大寫。 在界面中還能夠爲數據實體添加屬性和關聯屬性。app
Core Data屬性支持的數據類型以下dom
編譯以後,Xcode會自動生成Person的實體代碼文件,而且文件不會顯示在工程中,若是下圖中右側Codegen選擇Manual/None,則Xcode就不會自動生成代碼,咱們能夠本身手動生成。編程語言
- 手動生成實體類代碼,選中CoreDataTest.xcdatamodeld文件,而後在Mac菜單欄中選擇Editor,以下圖所示。一路Next就能夠了。
- 若是沒有選擇Manual/None,依然進行手動建立的話,則會與系統自動建立的文件發生衝突,這點須要注意。
- 你也能夠不要選擇Manual/None,直接使用系統建立好的NSManagedObject,一樣會有4個文件,只是在工程中是看不到的。
Swift中手動建立出來的是這樣2個文件fetch
還要注意編程語言的選擇,Swift或OC
講道理,這一節應該是Core Data堆棧的介紹與使用,不過因爲以前的文章中已經有了,這裏就不囉嗦了,咱們直接上圖和代碼。
以下圖所示,建立模型,我這裏直接建立一個命名爲Model的模型。
建立Person表,兩個屬性name和age,注意右側的Codegen
咱們這裏選擇Class Definition
,而後直接Command+B編譯代碼,Xcode會自動幫咱們生成Person+CoreDataClass.swift
和Person+CoreDataProperties.swift
文件
NSManagedObjectModel
注意modelURL中填寫的是模型文件的名字,而且後綴填寫
momd
import CoreData
lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = Bundle.main.url(forResource: "Model", withExtension: "momd")
let managedObjectModel = NSManagedObjectModel.init(contentsOf: modelURL!)
return managedObjectModel!
}()
複製代碼
NSPersistentStoreCoordinator
sqliteURL
是sqlite文件的路徑documentDir
是後面加載好了的Document路徑
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
let persistentStoreCoordinator = NSPersistentStoreCoordinator.init(managedObjectModel: managedObjectModel)
let sqliteURL = documentDir.appendingPathComponent("Model.sqlite")
let options = [NSMigratePersistentStoresAutomaticallyOption : true, NSInferMappingModelAutomaticallyOption : true]
var failureReason = "There was an error creating or loading the application's saved data."
do {
try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: sqliteURL, options: options)
} catch {
// Report any error we got.
var dict = [String: Any]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as Any?
dict[NSLocalizedFailureReasonErrorKey] = failureReason as Any?
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 6666, userInfo: dict)
print("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return persistentStoreCoordinator
}()
lazy var documentDir: URL = {
let documentDir = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first
return documentDir!
}()
複製代碼
NSManagedObjectContext
lazy var context: NSManagedObjectContext = {
let context = NSManagedObjectContext.init(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
context.persistentStoreCoordinator = persistentStoreCoordinator
return context
}()
複製代碼
我通常是把數據存儲方法封裝到一個CoreDataManager中,這樣在之後的使用中比較方便。固然,你也能夠根據本身的需求靈活運用。
建立一個繼承自NSObject
的CoreDataManager.swfit
文件,而且import CoreData
實現CoreDataManager
的單例,而且拿到AppDelegate中剛纔懶加載的NSManagedObjectContext
swift中建立單例比較方便,直接
static let shared = CoreDataManager()
// 單例
static let shared = CoreDataManager()
// 拿到AppDelegate中建立好了的NSManagedObjectContext
lazy var context: NSManagedObjectContext = {
let context = ((UIApplication.shared.delegate) as! AppDelegate).context
return context
}()
複製代碼
除了查詢數據,其他對數據進行增刪改的時候,都別忘記調用這個方法,只有這個方法執行ok,纔算增刪改完成。
// 更新數據
private func saveContext() {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
複製代碼
- 首先運用
NSEntityDescription
建立出person
- 而後爲
person
賦值,最終調用saveContext()
方法保存數據
// 增長數據
func savePersonWith(name: String, age: Int16) {
let person = NSEntityDescription.insertNewObject(forEntityName: "Person", into: context) as! Person
person.name = name
person.age = age
saveContext()
}
複製代碼
- 若是是經過系統自動生成的CoreData文件,
Person
會自帶一個fetchRequest()
的方法,咱們能夠直接經過Person.fetchRequest()
的方式拿到person
的NSFetchRequest
對象- 而後經過
context
的fetch(fetchRequest)
方法拿到數據數組
// 獲取全部數據
func getAllPerson() -> [Person] {
let fetchRequest: NSFetchRequest = Person.fetchRequest()
do {
let result = try context.fetch(fetchRequest)
return result
} catch {
fatalError();
}
}
複製代碼
- 能夠利用
NSPredicate
來過濾出符合必定條件的數據- 而
NSFetchRequest
中有predicate
這樣一個屬性
// 根據姓名獲取數據
func getPersonWith(name: String) -> [Person] {
let fetchRequest: NSFetchRequest = Person.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "name == %@", name)
do {
let result: [Person] = try context.fetch(fetchRequest)
return result
} catch {
fatalError();
}
}
複製代碼
- 首先獲取到想要修改的數據
- 而後循環修改就能夠了
- 最後別忘記
save
// 根據姓名修改數據
func changePersonWith(name: String, newName: String, newAge: Int16) {
let fetchRequest: NSFetchRequest = Person.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "name == %@", name)
do {
// 拿到符合條件的全部數據
let result = try context.fetch(fetchRequest)
for person in result {
// 循環修改
person.name = newName
person.age = newAge
}
} catch {
fatalError();
}
saveContext()
}
複製代碼
- 與修改數據同樣,首先拿到符合刪除條件的數據
- 循環調用
context
的delete()
方法就能夠了- 最後別忘記
save
// 根據姓名刪除數據
func deleteWith(name: String) {
let fetchRequest: NSFetchRequest = Person.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "name == %@", name)
do {
let result = try context.fetch(fetchRequest)
for person in result {
context.delete(person)
}
} catch {
fatalError();
}
saveContext()
}
複製代碼
- 獲取全部數據
- 循環刪除
save
// 刪除全部數據
func deleteAllPerson() {
// 這裏直接調用上面獲取全部數據的方法
let result = getAllPerson()
// 循環刪除全部數據
for person in result {
context.delete(person)
}
saveContext()
}
複製代碼
本文運用一個簡單的示例來講明swift中如何使用CoreData
,更多用法或注意事項就不一一列舉了。
本文Demo:github.com/remember17/…
做者GitHub:github.com/remember17