swift 2 時(shí)代的 coredata 增刪改查

寫(xiě)這個(gè)是對(duì)coredata這個(gè)內(nèi)置的數(shù)據(jù)庫(kù)的一個(gè)總結(jié)

默認(rèn)讀者已經(jīng)對(duì) coredata 有了基本了解,并未涉及 relationships 等高級(jí)功能,只是對(duì)coredata的各類(lèi)基本操作做個(gè)總結(jié)

通過(guò)這些簡(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,打開(kāi)項(xiàng)目中的 xcdatamodeld 文件,在右邊的數(shù)據(jù)模型編輯器的底部工具欄點(diǎn)擊 Add Entity 添加實(shí)體。
同時(shí)在屬性欄中對(duì)實(shí)體命名進(jìn)行修改,并在 **Attribute
** 欄目中添加 **userID
userName
userImage
** 三個(gè)屬性用以存儲(chǔ)客戶(hù)基本資料。

Paste_Image.png

3,還要為每一個(gè)實(shí)體生成一個(gè)對(duì)應(yīng)的 **NSManagedObject
** 子類(lèi),通過(guò)類(lèi)的成員屬性來(lái)訪(fǎng)問(wèn)和獲取數(shù)據(jù)。
新建選擇 **Core Data
** 項(xiàng)下面 **NSManagedObject subclass
** 類(lèi)型文件,生成該實(shí)體同名的類(lèi)。

Paste_Image.png

這一步不做也可以,不做就是用kvc的方式訪(fǎng)問(wèn),但做了可以用訪(fǎng)問(wèn)器下標(biāo)的方式訪(fǎng)問(wèn)

真正用起來(lái)方便很多,不容易出錯(cuò)外,訪(fǎng)問(wèn)器的效率還比kvc高那么點(diǎn),建議生成該類(lèi)

當(dāng)然這中間有個(gè)坑,放在最后說(shuō)

4,下面就是很正常的勾選和選擇存放地點(diǎn)

Paste_Image.png

語(yǔ)言 swift


Paste_Image.png

二,Core Data的使用

開(kāi)始代碼之前先了解幾個(gè)概念

(1)NSManagedObjectModel(被管理的對(duì)象模型) 相當(dāng)于實(shí)體,不過(guò)它包含 了實(shí)體間的關(guān)系

(2)NSManagedObjectContext(被管理的對(duì)象上下文) 操作實(shí)際內(nèi)容
作用:插入數(shù)據(jù) 查詢(xún) 更新 刪除

(3)NSPersistentStoreCoordinator(持久化存儲(chǔ)助理) 相當(dāng)于數(shù)據(jù)庫(kù)的連接器

(4)NSFetchRequest(獲取數(shù)據(jù)的請(qǐng)求) 相當(dāng)于查詢(xún)語(yǔ)句

(5)NSPredicate(相當(dāng)于查詢(xún)條件)

(6)NSEntityDescription(實(shí)體結(jié)構(gòu))

(7)后綴名為.xcdatamodel的包 里面的.xcdatamodel文件,用數(shù)據(jù)模型編輯器編輯

編譯后為.momd或.mom文件,這就是為什么文件中沒(méi)有這個(gè)東西,而我們的程序中用到這個(gè)東西而不會(huì)報(bào)錯(cuò)的原因

了解后我們可以開(kāi)始碼田了

1,首先在代碼中引入CoreData庫(kù)###

import CoreData

2,為了方便訪(fǎng)問(wèn),把同樣的東西先放進(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),通過(guò)類(lèi)的成員屬性來(lái)訪(fǎng)問(wèn)和獲取數(shù)據(jù)。新建選擇 Core Data 項(xiàng)下面 NSManagedObject subclass 類(lèi)型文件,生成該實(shí)體同名的類(lèi)
        let user = NSEntityDescription.insertNewObjectForEntityForName(entityName, inManagedObjectContext: managedContext) as! UserData
        //然后就可以用下標(biāo)方式賦值
        user.userID = data[0]
        user.userName = data[1]
        user.userImage = data[2]

        // 把‘暫存器’中的東西存到磁盤(pán)中
        do{
            try managedContext.save()
            print("save success")
        }catch{
            print("Could not save!")
        }
    }//func saveCoreData(){

如果上面沒(méi)有生成 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 的值,

返回類(lèi)型可以隨便選,這里初定為只返回名字,當(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,查詢(xún)記錄###

用法:條件輸入查詢(xún)條件 condition = "userID= '1' "
條件 condition 為nil的時(shí)候則返回所有資料,和 loadCoreData 功能相同

    func searchCoreData(condition:String?) -> [UserData]?{

        //必須使用新 fetch
        let fetchRequest:NSFetchRequest = NSFetchRequest()
        fetchRequest.fetchLimit = 10 //限定查詢(xún)結(jié)果的數(shù)量
        fetchRequest.fetchOffset = 0 //查詢(xún)的偏移量

        //設(shè)置數(shù)據(jù)請(qǐng)求的實(shí)體結(jié)構(gòu)
        fetchRequest.entity = NSEntityDescription.entityForName("UserData", inManagedObjectContext: managedContext)

        //設(shè)置查詢(xún)條件,條件為nil的時(shí)候則返回所有資料
        if let _ = condition {
            fetchRequest.predicate = NSPredicate(format: condition!, "")
        }

        //查詢(xún)操作
        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的情況,用于查詢(xún)

"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è)字符串開(kāi)頭
"name ENDSWITH[d] 'ang'" //以某個(gè)字符串結(jié)束
注:[c]不區(qū)分大小寫(xiě)[d]不區(qū)分發(fā)音符號(hào)即沒(méi)有重音符號(hào)[cd]既不區(qū)分大小寫(xiě),也不區(qū)分發(fā)音符號(hào)。

(5)通配符:LIKE
例:"name LIKE[cd] 'er'" // * 代表通配符,Like也接受[cd].
"name LIKE[cd] '???er*'"

(6)正則表達(dá)式:MATCHES
例:let regex = "^A.+e$"; //以A開(kāi)頭,e結(jié)尾
"name MATCHES %@",regex

基本可以應(yīng)付常見(jiàn)情況了

6,刪除單條數(shù)據(jù)

condition 同上的條件用法

    func delCoreData(condition : String){
        
        //設(shè)置查詢(xún)條件
        fetchRequest.predicate = NSPredicate(format: condition, "")

        //查詢(xún)操作
        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í)刪除所有記錄

不過(guò)不知道出于什么原因,蘋(píng)果在 ios9 之前都沒(méi)有相關(guān)的方法提供可以一次性的刪除所有數(shù)據(jù)

最常見(jiàn)的做法是用刪單條的方法建立 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()

Paste_Image.png

刪除 userName 等于 12331 的記錄

CoreDataFunc().delCoreData("userName= '12331'")

Paste_Image.png

顯示所有記錄

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)
}
}

Paste_Image.png

保存一條信息

let data = [ "12", "12adsfasdfasdf", "baidu"]
CoreDataFunc().saveCoreData(data)

Paste_Image.png
中間建立 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

}

以上

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,578評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,701評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,691評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,974評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,694評(píng)論 6 413
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 56,026評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,015評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,193評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,719評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,668評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,151評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,846評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,255評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,592評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,394評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,635評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容