iOS 數(shù)據(jù)庫(kù)

一漱挎,F(xiàn)MDB

  • 1,F(xiàn)MDB 的基本使用
    創(chuàng)建數(shù)據(jù)庫(kù)
FMDatabase * db = [FMDatabase databaseWithPath:dbPath];
if ([db open]) {
        NSLog(@"數(shù)據(jù)庫(kù)打開了");
}else{
        NSLog(@"數(shù)據(jù)庫(kù)打開失敗");
}
return db;

創(chuàng)建表單

NSFileManager * fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: self.dbPath]) {
        FMDatabase * db = [FMDatabase databaseWithPath:self.dbPath];
        if ([db open]) {
            NSString * sql = @"CREATE TABLE 'User' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 'name' VARCHAR(30),'password' VARCHAR(30))";
            BOOL res = [db executeUpdate:sql];
            if (res) {
                NSLog(@"create table success");

            }else{
                NSLog(@"create table error");
            }
            [db close];
        } else{
            NSLog(@"open db error");
        }
    }

static int idx = 1;
FMDatabase * db = [FMDatabase databaseWithPath:self.dbPath];
if ([db open]) {
        NSString * sql = @"insert into user (name,password) values(?, ?)";
        NSString * name = [NSString stringWithFormat:@"tangqiao%d",idx++];
        BOOL res = [db executeUpdate:sql, name ,@"boy"];
        if (res) {
            NSLog(@"insert data success");
        }else
        {
            NSLog(@"insert data error");
        }
    }

FMDatabase * db = [FMDatabase databaseWithPath:self.dbPath];
    if ([db open]) {
        NSString * sql = @"delete from user";
        BOOL res = [db executeUpdate:sql];
        if (res) {
            NSLog(@"delete db success");
        }else{
            NSLog(@"delete db error");
        }
        [db close];
    }

FMDatabase * db = [FMDatabase databaseWithPath:self.dbPath];
if ([db open]) {
        NSString * sql = @"update user set name = ? where id = ?";
        BOOL res = [db executeUpdate:sql,@"新的名字",@(483)];
        if (res) {
            NSLog(@"uodate db success");
        }else{
            NSLog(@"uodate db error");
        }
}

FMDatabase * db = [FMDatabase databaseWithPath:self.dbPath];
    if ([db open]) {
        NSString * sql = @"select * from user";
        FMResultSet * rs = [db executeQuery:sql];
        while ([rs next]) {
            int userId = [rs intForColumn:@"id"];
            NSString * name = [rs stringForColumn:@"name"];
            NSString * pass = [rs stringForColumn:@"password"];
            NSLog(@"userid = %d,name = %@,password = %@",userId,name,pass);
        }
        [db close];
    }

FMDatabase這個(gè)類, 他不是線程安全的, 如果在多個(gè)線程中同時(shí)使用一個(gè)FMDataBase對(duì)象來(lái)存取數(shù)據(jù)的話, 有可能會(huì)發(fā)生數(shù)據(jù)錯(cuò)亂,因此為了保證線程安全, 要使用FMDatabaseQueue這個(gè)類來(lái)操作數(shù)據(jù)仗哨。

FMDatabaseQueue * queue = [FMDatabaseQueue databaseQueueWithPath:self.dbPath];
dispatch_queue_t q1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t q2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(q1, ^{
        for (int i = 0; i < 100; i++) {
            [queue inDatabase:^(FMDatabase * _Nonnull db) {
                NSString * sql = @"insert into user (name,password) values(?,?)";
                NSString * name = [NSString stringWithFormat:@"queue11 %d",I];
                BOOL res = [db executeUpdate:sql,name,@"boy"];
                NSLog(@"currentThread = %@",[NSThread currentThread]);
                if (res) {
                    NSLog(@"q1 add data success: %@",name);
                }else{
                    NSLog(@"q1 add data error: %@",name);
                }
            }];
        }
    });
dispatch_async(q2, ^{
        for (int i = 0; i < 100; i++) {
            [queue inDatabase:^(FMDatabase * _Nonnull db) {
                NSString * sql = @"insert into user (name,password) values(?,?)";
                NSString * name = [NSString stringWithFormat:@"queue22 %d",I];
                BOOL res = [db executeUpdate:sql,name,@"boy"];
                NSLog(@"currentThread = %@",[NSThread currentThread]);
                if (res) {
                    NSLog(@"q2 add data success: %@",name);
                }else{
                    NSLog(@"q2 add data error: %@",name);
                }
            }];
        }
});
  • 2晚吞,F(xiàn)MDB的二次封裝
    問(wèn)題:
    1, 直接存取模型,模型中包含數(shù)組萌踱,字典葵礼,其他模型屬性,這時(shí)候改怎么處理并鸵,

在遇到其他類型或者自定義類型時(shí)鸳粉,全部轉(zhuǎn)化成字符串,模型轉(zhuǎn)字符串园担,字典和數(shù)組轉(zhuǎn)字符串届谈,下面這些第三方庫(kù)已經(jīng)幫我們做了這些處理。
BGFMDB
LKDBHelper-SQLite-ORM
JRDB

2粉铐,模型增加字段疼约,表增加字段了,這時(shí)候該怎么處理

先從表中取出所有字段蝙泼,然后和模型的所有成員變量比較程剥,如果有不同的,表示模型增加字段了汤踏,這時(shí)候就插入字段织鲸。

二,WCDB

WCDB 是微信團(tuán)隊(duì)開源的一款高效溪胶、完整搂擦、易用的移動(dòng)數(shù)據(jù)庫(kù)框架,優(yōu)點(diǎn):1哗脖,開發(fā)者無(wú)須為了拼接SQL的字符串而寫一大坨膠水代碼瀑踢,2扳还,WCDB支持多線程讀與讀、讀與寫并發(fā)執(zhí)行橱夭,寫與寫串行執(zhí)行氨距。缺點(diǎn):需使用Objective-C++,導(dǎo)入 <WCDB/WCDB.h> 的類必須改成.mm 類型棘劣。

官方文檔:iOS macOS使用教程

  • 1俏让,WCDB 的基本使用
    WCDB會(huì)在第一次訪問(wèn)數(shù)據(jù)庫(kù)時(shí),自動(dòng)打開數(shù)據(jù)庫(kù)茬暇,不需要開發(fā)者主動(dòng)操作首昔。
  • 2,WCDB 的封裝糙俗,隔離c++ 代碼
    項(xiàng)目引入WCDB 的類都需要改成.mm 勒奇,這樣有點(diǎn)不太好,所以我創(chuàng)建了管理類臼节,簡(jiǎn)單的封裝增刪改查的基本操作撬陵,但是像 where 和 limit 這樣的c++ 類型不太好封裝,所以還是沒(méi)有充分使用WCDB 的全部功能网缝。具體案例請(qǐng)看wcdbDemo巨税。
  • 3, WCTTableCoding文件模版
    通過(guò)這個(gè)模板,我們?cè)趧?chuàng)建模型的時(shí)候粉臊,會(huì)自動(dòng)為我們創(chuàng)建WCTTableCoding的category草添。
    已獲取 WCDB 的 Github 倉(cāng)庫(kù)的開發(fā)者,可以手動(dòng)運(yùn)行 cd path-to-your-wcdb-dir/tools/templates; sh install.sh;

安裝完成之后:


image.png
image.png
  • 4, 模型增加字段, 表格字段不同
  • 5, 模型當(dāng)中嵌套模型

三扼仲,CoreData

CoreData - 基礎(chǔ)使用
MagicalRecord使用

  • 1远寸,基本使用

1,新建項(xiàng)目屠凶,創(chuàng)建后綴為.xcdatamodeld的模型文件

image.png

2驰后,添加實(shí)體
點(diǎn)擊列表下方的Add Entity按鈕,會(huì)彈出Add Entity矗愧、Add Fetch Request灶芝、Add Configuration選項(xiàng),可以添加實(shí)體唉韭、請(qǐng)求模板夜涕、配置信息。這里先選擇Add Entity來(lái)添加一個(gè)實(shí)體属愤,命名為Person女器。
添加Person實(shí)體后,會(huì)發(fā)現(xiàn)一個(gè)實(shí)體對(duì)應(yīng)著三部分內(nèi)容住诸,Attributes驾胆、Relationships涣澡、Fetched Properties,分別對(duì)應(yīng)著屬性俏拱、關(guān)聯(lián)關(guān)系暑塑、獲取操作吼句。

3锅必,創(chuàng)建托管對(duì)象類文件
點(diǎn)擊后綴名為.xcdatamodeld的模型文件,選擇Xcode的Editor -> Create NSManagedObject Subclass -> 選擇模型文件 -> 選擇實(shí)體惕艳,生成Department實(shí)體對(duì)應(yīng)的托管對(duì)象類文件搞隐。


image.png

切換語(yǔ)言
點(diǎn)擊后綴名為.xcdatamodeld的模型文件,最右側(cè)有個(gè)language 的選項(xiàng)远搪,切換下劣纲。


image.png

到這里創(chuàng)建文件就算完成了。

4,CoreData增刪改查
創(chuàng)建NSManagedObjectContext
NSManagedObjectContext初始化方法的枚舉值參數(shù)主要有三個(gè)類型:
NSConfinementConcurrencyType 如果使用init方法初始化上下文谁鳍,默認(rèn)就是這個(gè)并發(fā)類型癞季。在iOS9之后已經(jīng)被蘋果廢棄,不建議用這個(gè)API倘潜,調(diào)用某些比較新的CoreData的API可能會(huì)導(dǎo)致崩潰绷柒。
NSPrivateQueueConcurrencyType 私有并發(fā)隊(duì)列類型,操作都是在子線程中完成的涮因。
NSMainQueueConcurrencyType 主并發(fā)隊(duì)列類型废睦,如果涉及到UI相關(guān)的操作,應(yīng)該考慮使用這個(gè)參數(shù)初始化上下文养泡。

- (NSManagedObjectContext * )contextWithModel:(NSString *)modelName;
{
    NSManagedObjectContext * context= [[NSManagedObjectContext alloc] initWithConcurrencyType:(NSMainQueueConcurrencyType)];
    NSURL * url = [[NSBundle mainBundle] URLForResource:modelName withExtension:@"momd"];
    NSManagedObjectModel * model = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
    NSPersistentStoreCoordinator * coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    NSString * path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
    path = [path stringByAppendingFormat:@"/%@.sqlite", modelName];
    NSLog(@"path = %@",path);
/*
 NSMigratePersistentStoresAutomaticallyOption設(shè)置為YES嗜湃,CoreData會(huì)試著把低版本的持久化存儲(chǔ)區(qū)遷移到最新版本的模型文件。
 NSInferMappingModelAutomaticallyOption設(shè)置為YES澜掩,CoreData會(huì)試著以最為合理地方式自動(dòng)推斷出源模型文件的實(shí)體中购披,某個(gè)屬性到底對(duì)應(yīng)于目標(biāo)模型文件實(shí)體中的哪一個(gè)屬性
*/
    NSDictionary * options = @{NSMigratePersistentStoresAutomaticallyOption : @YES,
                               NSInferMappingModelAutomaticallyOption : @YES
                               };
//    options : 用于設(shè)置數(shù)據(jù)庫(kù)增刪字段和數(shù)據(jù)庫(kù)升級(jí)
    [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:path] options:options error:nil];
    
    context.persistentStoreCoordinator = coordinator;
    return context;
}

持久化存儲(chǔ)調(diào)度器(NSPersistentStoreCoordinator)

NSPersistentStoreCoordinator有四種可選的持久化存儲(chǔ)方案,用得最多的是SQLite的方式肩榕。其中Binary和XML這兩種方式刚陡,在進(jìn)行數(shù)據(jù)操作時(shí),需要將整個(gè)文件加載到內(nèi)存中点把,這樣對(duì)內(nèi)存的消耗是很大的橘荠。
NSSQLiteStoreType : SQLite數(shù)據(jù)庫(kù)
NSXMLStoreType : XML文件
NSBinaryStoreType : 二進(jìn)制文件
NSInMemoryStoreType : 直接存儲(chǔ)在內(nèi)存中

    static int i = 1;
    Employee * emp = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:self.modelMOC];
    emp.name = [NSString stringWithFormat:@"zdq_%@",@(i)];
    emp.userId = [NSString stringWithFormat:@"%@",@(i)];
    emp.height = 1.30 + i / 10.0;
    NSLog(@"height = %@",@(emp.height));
    NSError * error = nil;
    if (self.modelMOC.hasChanges) {
        [self.modelMOC save:&error];
    }
    if (error) {
        NSLog(@"insert error = %@",error);
    }
    i ++;

    NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"userId = %@",@"2"];
    request.predicate = predicate;
    NSError * error = nil;
    NSArray * arr = [self.modelMOC executeFetchRequest:request error:&error];
    
    [arr enumerateObjectsUsingBlock:^(Employee * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [self.modelMOC deleteObject:obj];
    }];
    if ([self.modelMOC hasChanges]) {
        [self.modelMOC save:nil];
    }
    if (error) {
        NSLog(@"delete error = %@",error);
    }

    NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"userId = %@",@"1"];
    request.predicate = predicate;
    NSError * error = nil;
    NSArray * arr = [self.modelMOC executeFetchRequest:request error:&error];
    [arr enumerateObjectsUsingBlock:^(Employee * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        obj.name = @"更新了";
    }];
    if ([self.modelMOC hasChanges]) {
        [self.modelMOC save:nil];
    }
    if (error) {
        NSLog(@"update error = %@",error);
    }

NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
NSError * error = nil;
NSArray * arr = [self.modelMOC executeFetchRequest:request error:&error];
 [arr enumerateObjectsUsingBlock:^(Employee *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"name = %@,userId = %@",obj.name,obj.userId);
    }];
    if (error) {
        NSLog(@"query error = %@",error);
    }

查詢排序

    NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
    NSError * error = nil;
    NSSortDescriptor * sort = [NSSortDescriptor sortDescriptorWithKey:@"height" ascending:YES];
    request.sortDescriptors = @[sort];
    NSArray * arr = [self.modelMOC executeFetchRequest:request error:&error];
    [arr enumerateObjectsUsingBlock:^(Employee *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"name = %@,userId = %@,height = %@",obj.name,obj.userId,@(obj.height));
    }];

分頁(yè)查詢

 NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
    request.fetchOffset = 1;
    request.fetchLimit = 3;
//    NSSortDescriptor * sort = [NSSortDescriptor sortDescriptorWithKey:@"userId" ascending:YES];
//    request.sortDescriptors = @[sort];
    NSError * error = nil;
    NSArray * arr = [self.modelMOC executeFetchRequest:request error:&error];
    [arr enumerateObjectsUsingBlock:^(Employee *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"name = %@,userId = %@,height = %@",obj.name,obj.userId,@(obj.height));
    }];
    if (error) {
        NSLog(@"page query error = %@",error);
    }

批量更新

    NSBatchUpdateRequest * request = [NSBatchUpdateRequest batchUpdateRequestWithEntityName:@"Employee"];
    request.resultType = NSUpdatedObjectsCountResultType;
    request.propertiesToUpdate = @{@"height" : @(2.11)};
    NSError * error = nil;
    NSBatchUpdateResult * result = [self.modelMOC executeRequest:request error:&error];
    NSLog(@"update count %@",@([result.result integerValue]));
    if (error) {
        NSLog(@"batch update error = %@",error);
    }
    [self.modelMOC refreshAllObjects];

批量刪除

NSFetchRequest * request = [NSFetchRequest fetchRequestWithEntityName:@"Employee"];
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"height > %@",@(2.0)];
request.predicate = predicate;
NSBatchDeleteRequest * deleteRequest = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];
deleteRequest.resultType = NSBatchDeleteResultTypeCount;
NSError * error = nil;
NSBatchDeleteResult * result = [self.modelMOC executeRequest:deleteRequest error:&error];
NSLog(@"update count %@",@([result.result integerValue]));
if (error) {
        NSLog(@"batch update error = %@",error);
}
[self.modelMOC refreshAllObjects];
  • 2,數(shù)據(jù)庫(kù)升級(jí)

在開發(fā)中經(jīng)常會(huì)有模型文件增加字段的情況出現(xiàn)郎逃,如果新版本增加字段了哥童,不考慮兼容之前版本,那么上線之后APP就會(huì)崩潰褒翰。

創(chuàng)建新版本模型文件
選中需要做遷移的模型文件 -> 點(diǎn)擊菜單欄Editor -> Add Model Version -> 選擇基于哪個(gè)版本的模型文件(一般都是選擇目前最新的版本)贮懈,新建模型文件完成匀泊。


image.png

創(chuàng)建完成之后


image.png

可以勾選當(dāng)前使用的模型文件


image.png

Mapping Model 遷移方案

  • 3,MagicalRecord框架使用
    國(guó)外開發(fā)者開源了一個(gè)基于CoreData封裝的第三方——MagicalRecord朵你,就像是FMDB封裝SQLite一樣各聘,MagicalRecord封裝的CoreData,使得原生的CoreData更加容易使用抡医。并且MagicalRecord降低了CoreData的使用門檻躲因,不用去手動(dòng)管理之前的PSC、MOC等對(duì)象忌傻。

根據(jù)Github上MagicalRecord的官方文檔大脉,MagicalRecord的優(yōu)點(diǎn)主要有三條:

  1. 清理項(xiàng)目中CoreData代碼
  2. 支持清晰、簡(jiǎn)單水孩、一行式的查詢操作
  3. 當(dāng)需要優(yōu)化請(qǐng)求時(shí)镰矿,可以獲取NSFetchRequest進(jìn)行修改

導(dǎo)入MagicalRecord

pod 'MagicalRecord', '2.3.2'

創(chuàng)建模型文件和之前的步驟一樣
基本設(shè)置,在APPdelegate 中 設(shè)置log 級(jí)別和數(shù)據(jù)庫(kù)名稱俘种。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
//    設(shè)置log級(jí)別
    [MagicalRecord setLoggingLevel:(MagicalRecordLoggingLevelVerbose)];
//    設(shè)置數(shù)據(jù)庫(kù)名稱
    [MagicalRecord setupCoreDataStackWithStoreNamed:SQLiteName];
    return YES;
}

內(nèi)存警告的時(shí)候秤标,清除

- (void)applicationWillTerminate:(UIApplication *)application {
//    清除
    [MagicalRecord cleanUp];
}

NSManagedObjectContext * context = [NSManagedObjectContext MR_defaultContext];
Person * p = [Person MR_createEntityInContext:context];
static int i = 1;
p.name = [NSString stringWithFormat:@"zdq%@",@(i)];
p.age = i + 10;
I++;
[context MR_saveToPersistentStoreAndWait];

    NSArray * arr = [Person MR_findByAttribute:@"age" withValue:[NSNumber numberWithInt:12]];
    [arr enumerateObjectsUsingBlock:^(Person *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [obj MR_deleteEntity];
    }];
    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

    NSArray * arr = [Person MR_findByAttribute:@"name" withValue:@"zdq2"];
    [arr enumerateObjectsUsingBlock:^(Person *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        obj.name = [NSString stringWithFormat:@"更新了"];
    }];
    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

    NSArray * arr = [Person MR_findAllSortedBy:@"age" ascending:YES];
    [arr enumerateObjectsUsingBlock:^(Person *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"name = %@,age = %@",obj.name,@(obj.age));
    }];

四,Relam

官方文檔
Realm在iOS中的簡(jiǎn)單使用
Realm數(shù)據(jù)庫(kù) 從入門到“放棄”

  • 1宙刘、Realm簡(jiǎn)介

Realm是由美國(guó)YCombinator孵化的創(chuàng)業(yè)團(tuán)隊(duì)歷時(shí)幾年打造苍姜,第一個(gè)專門針對(duì)移動(dòng)平臺(tái)設(shè)計(jì)的數(shù)據(jù)庫(kù)
Realm是一個(gè)跨平臺(tái)的移動(dòng)數(shù)據(jù)庫(kù)引擎,目前支持iOS荐类、Android平臺(tái)怖现,同時(shí)支持Objective-CSwift玉罐、Java屈嗤、React NativeXamarin等多種編程語(yǔ)言
Realm并不是對(duì)SQLite或者CoreData的簡(jiǎn)單封裝, 是由核心數(shù)據(jù)引擎C++打造吊输,是擁有獨(dú)立的數(shù)據(jù)庫(kù)存儲(chǔ)引擎饶号,可以方便、高效的完成數(shù)據(jù)庫(kù)的各種操作

  • 2季蚂、Realm的優(yōu)勢(shì)與亮點(diǎn)

開源茫船。Realm移動(dòng)端數(shù)據(jù)庫(kù)相關(guān)代碼已全部開源。數(shù)千開發(fā)者在GitHub上參與了相關(guān)工作扭屁。另外還有幾百個(gè)Realm數(shù)據(jù)庫(kù)相關(guān)的擴(kuò)展算谈。
簡(jiǎn)單易用:Core DataSQLite龐大的學(xué)習(xí)量和繁雜的代碼足以嚇退絕大多數(shù)剛?cè)腴T的開發(fā)者料滥,而換用Realm然眼,則可以極大地減少學(xué)習(xí)代價(jià)和學(xué)習(xí)時(shí)間,讓應(yīng)用及早用上數(shù)據(jù)存儲(chǔ)功能
跨平臺(tái):現(xiàn)在絕大多數(shù)的應(yīng)用開發(fā)并不僅僅只在iOS平臺(tái)上進(jìn)行開發(fā)葵腹,還要兼顧到Android平臺(tái)的開發(fā)高每。為兩個(gè)平臺(tái)設(shè)計(jì)不同的數(shù)據(jù)庫(kù)是不明智的屿岂,而使用Realm數(shù)據(jù)庫(kù),iOSAndroid無(wú)需考慮內(nèi)部數(shù)據(jù)的架構(gòu)鲸匿,調(diào)用Realm提供的API就可以完成數(shù)據(jù)的交換
線程安全爷怀。程序員無(wú)需對(duì)在不同線程中,對(duì)數(shù)據(jù)庫(kù)的讀取一致性做任何考慮带欢,Realm會(huì)保證每次讀取都得到一致的數(shù)據(jù)

  • 3,可視化工具Realm Browser

為了配合Realm的使用运授,Realm還提供了一個(gè)輕量級(jí)的數(shù)據(jù)庫(kù)查看工具Realm Browser,借助這個(gè)工具洪囤,開發(fā)者可以查看數(shù)據(jù)庫(kù)當(dāng)中的內(nèi)容徒坡,并執(zhí)行簡(jiǎn)單的插入和刪除操作

  • 4, 導(dǎo)入

可以通過(guò)pod 導(dǎo)入,

  pod 'Realm'
  • 5瘤缩,插件

Realm提供了一個(gè)Xcode插件,來(lái)方便的創(chuàng)建RLMObject類伦泥,這需要我們首先安裝相關(guān)的插件剥啤,打開Realm文件夾中的plugin/RealmPlugin.xcodeproj并進(jìn)行編譯,重啟Xcode之后插件即可生效

  • 6, 創(chuàng)建模型
    運(yùn)行插件之后就會(huì)出來(lái)這個(gè)選項(xiàng)


    image.png

    所有的模型必須繼承 RLMObject


    image.png

    static int i = 1;
    Student * student = [[Student alloc] initWithValue:@{@"age": @(i),@"name":[NSString stringWithFormat:@"zdq%@",@(i)],@"sex":@(YES)}];
//    第一種
//    RLMRealm * realm = [RLMRealm defaultRealm];
//    [realm beginWriteTransaction];
//    [realm addObject:student];
//    [realm commitWriteTransaction];
//    第二種
    RLMRealm * realm = [RLMRealm defaultRealm];
    [realm transactionWithBlock:^{
        [realm addObject:student];
    }];
    i++;

    RLMRealm * realm = [RLMRealm defaultRealm];
    RLMResults * resArr = [Student objectsInRealm:realm where:@"name = 'zdq1'"];
    Student * stu = resArr.firstObject;
    [realm transactionWithBlock:^{
        [realm deleteObject: stu];
    }];

RLMRealm * realm = [RLMRealm defaultRealm];
RLMResults * resArr = [Student objectsWhere:@"age == 2"];
for (NSInteger i = 0; i < resArr.count; i++) {
        Student * obj = [resArr objectAtIndex:i];
        [realm transactionWithBlock:^{
            obj.name = @"更新了";
        }];
}

RLMResults * resArr = [Student allObjects];
NSLog(@"resArr = %@",resArr);

條件查詢

RLMResults * resArr = [Student objectsWhere:@"age > 3"];
    NSLog(@"resArr = %@",resArr);
//    排序
    RLMResults * stuArr = [resArr sortedResultsUsingKeyPath:@"age" ascending:YES];
    NSLog(@"stuArr = %@",stuArr);

數(shù)據(jù)庫(kù)遷移

RLMRealmConfiguration * con = [RLMRealmConfiguration defaultConfiguration];
con.fileURL = [[[con.fileURL URLByDeletingLastPathComponent]
URLByAppendingPathComponent:userName] URLByAppendingPathExtension:@"realm"];
int newVersion = 1;
con.schemaVersion = newVersion;
[con setMigrationBlock:^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
if (oldSchemaVersion < newVersion) {
            NSLog(@"數(shù)據(jù)結(jié)構(gòu)會(huì)自動(dòng)遷移");
        }
}];
[RLMRealmConfiguration setDefaultConfiguration:con];
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末不脯,一起剝皮案震驚了整個(gè)濱河市府怯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌防楷,老刑警劉巖牺丙,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異复局,居然都是意外死亡冲簿,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門亿昏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)峦剔,“玉大人,你說(shuō)我怎么就攤上這事角钩×吣” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵递礼,是天一觀的道長(zhǎng)惨险。 經(jīng)常有香客問(wèn)我,道長(zhǎng)脊髓,這世上最難降的妖魔是什么辫愉? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮供炼,結(jié)果婚禮上一屋,老公的妹妹穿的比我還像新娘窘疮。我一直安慰自己,他們只是感情好冀墨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布闸衫。 她就那樣靜靜地躺著,像睡著了一般诽嘉。 火紅的嫁衣襯著肌膚如雪蔚出。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天虫腋,我揣著相機(jī)與錄音骄酗,去河邊找鬼。 笑死悦冀,一個(gè)胖子當(dāng)著我的面吹牛趋翻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盒蟆,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼踏烙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了历等?” 一聲冷哼從身側(cè)響起讨惩,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寒屯,沒(méi)想到半個(gè)月后荐捻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寡夹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年处面,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片要出。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸳君,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出患蹂,到底是詐尸還是另有隱情或颊,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布传于,位于F島的核電站囱挑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏沼溜。R本人自食惡果不足惜平挑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧通熄,春花似錦唆涝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至赏枚,卻和暖如春亡驰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背饿幅。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工凡辱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人栗恩。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓透乾,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親摄凡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子续徽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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