寫這個(gè)是對(duì)coredata這個(gè)內(nèi)置的數(shù)據(jù)庫(kù)的一個(gè)總結(jié)
默認(rèn)讀者已經(jīng)對(duì) coredata 有了基本了解逞频,并未涉及 relationships 等高級(jí)功能红伦,只是對(duì)coredata的各類基本操作做個(gè)總結(jié)
通過這些簡(jiǎn)單的命令彻桃,可以讓您很快做好一個(gè)數(shù)據(jù)庫(kù)的操作丙者,輕松構(gòu)建 todo 或記事本等需要操作本地?cái)?shù)據(jù)庫(kù)的 app
一淫半,準(zhǔn)備工作
1鸣个,創(chuàng)建項(xiàng)目的時(shí)候,勾選“**Use Core Data
**”吗蚌。完畢后在 **AppDelegate
** 中腿倚,會(huì)生成相關(guān)代碼。
如果想在已有的項(xiàng)目中新集成 coredata 請(qǐng)參考這里
2蚯妇,打開項(xiàng)目中的 xcdatamodeld 文件敷燎,在右邊的數(shù)據(jù)模型編輯器的底部工具欄點(diǎn)擊 Add Entity 添加實(shí)體。
同時(shí)在屬性欄中對(duì)實(shí)體命名進(jìn)行修改箩言,并在 **Attribute
** 欄目中添加 **userID
硬贯,userName
,userImage
** 三個(gè)屬性用以存儲(chǔ)客戶基本資料陨收。
3饭豹,還要為每一個(gè)實(shí)體生成一個(gè)對(duì)應(yīng)的 **NSManagedObject
** 子類,通過類的成員屬性來(lái)訪問和獲取數(shù)據(jù)务漩。
新建選擇 **Core Data
** 項(xiàng)下面 **NSManagedObject subclass
** 類型文件拄衰,生成該實(shí)體同名的類。
這一步不做也可以饵骨,不做就是用kvc的方式訪問翘悉,但做了可以用訪問器下標(biāo)的方式訪問
真正用起來(lái)方便很多,不容易出錯(cuò)外居触,訪問器的效率還比kvc高那么點(diǎn)妖混,建議生成該類
當(dāng)然這中間有個(gè)坑,放在最后說(shuō)
4轮洋,下面就是很正常的勾選和選擇存放地點(diǎn)
語(yǔ)言 swift
二制市,Core Data的使用
開始代碼之前先了解幾個(gè)概念
(1)NSManagedObjectModel(被管理的對(duì)象模型) 相當(dāng)于實(shí)體,不過它包含 了實(shí)體間的關(guān)系
(2)NSManagedObjectContext(被管理的對(duì)象上下文) 操作實(shí)際內(nèi)容
作用:插入數(shù)據(jù) 查詢 更新 刪除
(3)NSPersistentStoreCoordinator(持久化存儲(chǔ)助理) 相當(dāng)于數(shù)據(jù)庫(kù)的連接器
(4)NSFetchRequest(獲取數(shù)據(jù)的請(qǐng)求) 相當(dāng)于查詢語(yǔ)句
(5)NSPredicate(相當(dāng)于查詢條件)
(6)NSEntityDescription(實(shí)體結(jié)構(gòu))
(7)后綴名為.xcdatamodel的包 里面的.xcdatamodel文件弊予,用數(shù)據(jù)模型編輯器編輯
編譯后為.momd或.mom文件祥楣,這就是為什么文件中沒有這個(gè)東西,而我們的程序中用到這個(gè)東西而不會(huì)報(bào)錯(cuò)的原因
了解后我們可以開始碼田了
1块促,首先在代碼中引入CoreData庫(kù)###
import CoreData
2荣堰,為了方便訪問床未,把同樣的東西先放進(jìn)class###
class CoreDataFunc: NSObject {
//1 在我們想要保存或者獲取任何數(shù)據(jù)之前我們必須獲取NSManagedObjectContext竭翠,理解為暫存器
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
//2 entity的名字
let entityName:String = "UserData"
//3 系統(tǒng)想要的讀取數(shù)據(jù)的entity
var fetchRequest : NSFetchRequest{ return NSFetchRequest(entityName:entityName) }
}
3,保存數(shù)據(jù)###
用法:data 傳 ["ID", "名字", "頭像"]
func saveCoreData(data:[String]){
//為每一個(gè)實(shí)體生成一個(gè)對(duì)應(yīng)的 NSManagedObject 子類薇搁,通過類的成員屬性來(lái)訪問和獲取數(shù)據(jù)斋扰。新建選擇 Core Data 項(xiàng)下面 NSManagedObject subclass 類型文件,生成該實(shí)體同名的類
let user = NSEntityDescription.insertNewObjectForEntityForName(entityName, inManagedObjectContext: managedContext) as! UserData
//然后就可以用下標(biāo)方式賦值
user.userID = data[0]
user.userName = data[1]
user.userImage = data[2]
// 把‘暫存器’中的東西存到磁盤中
do{
try managedContext.save()
print("save success")
}catch{
print("Could not save!")
}
}//func saveCoreData(){
如果上面沒有生成 subclass ,那存儲(chǔ)的方式就得將 do 之前的內(nèi)容變成如下內(nèi)容
let entity = NSEntityDescription.entityForName(entityName, inManagedObjectContext: managedContext)
let user = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
user.setValue(data[0], forKey: "userID")
user.setValue(data[1], forKey: "userName")
user.setValue(data[2], forKey: "userImage")
4传货,獲取所有數(shù)據(jù)###
key 參數(shù)為 attribute 的值屎鳍,
返回類型可以隨便選,這里初定為只返回名字问裕,當(dāng)然也可以返回所有數(shù)據(jù)
func loadCoreData(key key:String = "userName") -> [String]{
var result : [String] = []
do{
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest)
for each in fetchedResults{
let name:String = each.valueForKey(key) as! String
result.append(name)
}
print("read success")
}catch{
print("load Data from coreData error")
}
return result
}//loadCoreData
5逮壁,查詢記錄###
用法:條件輸入查詢條件 condition = "userID= '1' "
條件 condition 為nil的時(shí)候則返回所有資料,和 loadCoreData 功能相同
func searchCoreData(condition:String?) -> [UserData]?{
//必須使用新 fetch
let fetchRequest:NSFetchRequest = NSFetchRequest()
fetchRequest.fetchLimit = 10 //限定查詢結(jié)果的數(shù)量
fetchRequest.fetchOffset = 0 //查詢的偏移量
//設(shè)置數(shù)據(jù)請(qǐng)求的實(shí)體結(jié)構(gòu)
fetchRequest.entity = NSEntityDescription.entityForName("UserData", inManagedObjectContext: managedContext)
//設(shè)置查詢條件粮宛,條件為nil的時(shí)候則返回所有資料
if let _ = condition {
fetchRequest.predicate = NSPredicate(format: condition!, "")
}
//查詢操作
do {
let fetchedObjects:[AnyObject]? = try managedContext.executeFetchRequest(fetchRequest)
guard fetchedObjects?.count > 0 else { return nil}
return fetchedObjects as? [UserData]
}
catch {
fatalError("could not search:\(error)")
}
}
這里可以使用的條件很豐富窥淆,相當(dāng)于 where 在數(shù)據(jù)庫(kù)中的用法
where userID == 1的情況,用于查詢
"userID= '1' "
主要牽扯到 NSPredicate 的用法
NSPredicate(format: "userName= 'dafadsf' ", "")
userName == dafadsf 的情況
>NSPredicate(format: "SELF MATCHES %@", "^[A-Za-z].+") //判斷字符串首字母是否為字母
Format:
(1)比較運(yùn)算符>,<,==,>=,<=,!=
可用于數(shù)值及字符串
例:@"number > 100"
(2)范圍運(yùn)算符:IN巍杈、BETWEEN
例:"number BETWEEN {1,5}"
"address IN {'shanghai','beijing'}"
(3)字符串本身:SELF
例:"SELF == 'APPLE'"
(4)字符串相關(guān):BEGINSWITH忧饭、ENDSWITH、CONTAINS
例:"name CONTAINS[cd] 'ang'" //包含某個(gè)字符串
"name BEGINSWITH[c] 'sh'" //以某個(gè)字符串開頭
"name ENDSWITH[d] 'ang'" //以某個(gè)字符串結(jié)束
注:[c]不區(qū)分大小寫[d]不區(qū)分發(fā)音符號(hào)即沒有重音符號(hào)[cd]既不區(qū)分大小寫筷畦,也不區(qū)分發(fā)音符號(hào)词裤。
(5)通配符:LIKE
例:"name LIKE[cd] 'er'" // * 代表通配符,Like也接受[cd].
"name LIKE[cd] '???er*'"
(6)正則表達(dá)式:MATCHES
例:let regex = "^A.+e$"; //以A開頭,e結(jié)尾
"name MATCHES %@",regex
基本可以應(yīng)付常見情況了
6鳖宾,刪除單條數(shù)據(jù)
condition 同上的條件用法
func delCoreData(condition : String){
//設(shè)置查詢條件
fetchRequest.predicate = NSPredicate(format: condition, "")
//查詢操作
do {
let fetchedObjects:[AnyObject]? = try managedContext.executeFetchRequest(fetchRequest)
guard fetchedObjects?.count > 0 else { print("not found in coredata"); return }
managedContext.deleteObject(fetchedObjects![0] as! NSManagedObject)
try managedContext.save()
print("del success")
}catch{
print("CoreData delete data fail")
}
}//func delCoreData
7吼砂,刪除所有數(shù)據(jù)###
該條多用于退出app時(shí)刪除所有記錄
不過不知道出于什么原因,蘋果在 ios9 之前都沒有相關(guān)的方法提供可以一次性的刪除所有數(shù)據(jù)
最常見的做法是用刪單條的方法建立 for 循環(huán)一個(gè)一個(gè)刪鼎文,這樣的后果就是效率很低
所以最快的方法就是把生成的 sqlite 數(shù)據(jù)文件整個(gè)刪除帅刊,swift 2 中刪除方法如下
func removeCoreData(){
guard let psc = managedContext.persistentStoreCoordinator else { return }
guard let store = psc.persistentStores.last as NSPersistentStore? else { return }
let storeUrl = psc.URLForPersistentStore(store)
managedContext.performBlockAndWait() {
self.managedContext.reset()
do{
try psc.removePersistentStore(store)
try NSFileManager.defaultManager().removeItemAtURL(storeUrl)
try psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeUrl, options: nil)
print("remove coredata file success!")
}catch{
print("remove coredata file error")
}
}//managedContext.performBlockAndWait()
}//func removeCoreData()
ios 9 以后出來(lái)的方法
if #available(iOS 9.0, *) {
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
// delegate objects
let myManagedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let myPersistentStoreCoordinator = (UIApplication.sharedApplication().delegate as! AppDelegate).persistentStoreCoordinator
// perform the delete
do {
try myPersistentStoreCoordinator.executeRequest(deleteRequest, withContext: myManagedObjectContext)
} catch let error as NSError {
print(error)
}
return
}//if #available(iOS 9.0, *)
ok,可以這樣調(diào)用
刪除整個(gè)數(shù)據(jù)庫(kù)內(nèi)容
CoreDataFunc().removeCoreData()
刪除 userName 等于 12331 的記錄
CoreDataFunc().delCoreData("userName= '12331'")
顯示所有記錄
func show(){
guard let d = CoreDataFunc().searchCoreData(nil) else { print("no data in coredata"); return }
for i in d {
print(i.userID, i.userName, i.userImage)
}
}
保存一條信息
let data = [ "12", "12adsfasdfasdf", "baidu"]
CoreDataFunc().saveCoreData(data)
中間建立 subclass 有個(gè)坑######
某些特殊的情況下漂问,建立 subclass 存儲(chǔ)的時(shí)候會(huì)發(fā)現(xiàn)無(wú)法存儲(chǔ)的情況赖瞒,這時(shí)候要在 這個(gè)subclass 文件前加上
@objc(className)
例:
@objc(UserData)
class UserData: NSManagedObject {
// Insert code here to add functionality to your managed object subclass
}
以上