iOS WCDB 傻瓜教程

這里只是提到了一些基礎(chǔ)是用法。深度用法阳惹,可以前往官網(wǎng)學(xué)習(xí)谍失。 關(guān)于WCDB的背景和優(yōu)缺點(diǎn),這里也不做介紹莹汤,大家可以自行百度快鱼。

類字段綁定(ORM)

在WCDB內(nèi),ORM(Object Relational Mapping)是指
將一個(gè)ObjC的類纲岭,映射到數(shù)據(jù)庫的表和索引止潮;
將類的property,映射到數(shù)據(jù)庫表的字段唆樊;
這一過程。通過ORM仓洼,可以達(dá)到直接通過Object進(jìn)行數(shù)據(jù)庫操作,省去拼裝過程的目的舌缤。

WCDB通過內(nèi)建的宏來實(shí)現(xiàn)ORM的功能。

首先創(chuàng)建一個(gè)model:

.h
#import "DetailModel.h"
@interface Draft1 : NSObject

@property int localID;
@property(retain) NSString *content;
@property(retain) NSString *title;
@property(retain) NSDate *createTime;
@property(retain) NSDate *modifiedTime;
@property(assign) int unused;

@property (nonatomic, strong) DetailModel *model;

@end


.mm
#import <WCDB/WCDB.h>
@implementation Draft1

WCDB_IMPLEMENTATION(Draft1)
WCDB_SYNTHESIZE(Draft1, localID)
WCDB_SYNTHESIZE(Draft1, content)
WCDB_SYNTHESIZE(Draft1, createTime)
WCDB_SYNTHESIZE(Draft1, modifiedTime)
WCDB_SYNTHESIZE(Draft1, model)
WCDB_SYNTHESIZE(Draft1, title)

//主鍵
WCDB_PRIMARY(Draft1, localID)

WCDB_INDEX(Draft1, "_index", createTime)

@end

由于WCDB是結(jié)合c++寫的,引用#import <WCDB/WCDB.h>的文件.m里面都要改成.mm后綴的,所以一般上為了隔離model,不讓view喝viewController里面也改成.mm后綴的,我們寫一個(gè)model的分類,遵守WCTTableCoding協(xié)議并寫WCDB_PROPERTY(),WCDB編譯后項(xiàng)目里有快捷創(chuàng)建model類,直接創(chuàng)建出分類.

創(chuàng)建對應(yīng)model的分類

.h
#import <WCDB/WCDB.h>

NS_ASSUME_NONNULL_BEGIN

@interface Draft1 (wcdb)<WCTTableCoding>

WCDB_PROPERTY(localID)
WCDB_PROPERTY(content)
WCDB_PROPERTY(title)
WCDB_PROPERTY(createTime)
WCDB_PROPERTY(modifiedTime)

WCDB_PROPERTY(model)

@end

將一個(gè)已有的ObjC類進(jìn)行ORM綁定的過程如下:

定義該類遵循WCTTableCoding協(xié)議囚似。可以在類聲明上定義募狂,也可以通過文件模版在category內(nèi)定義谓罗。

  1. 使用WCDB_PROPERTY宏在頭文件聲明需要綁定到數(shù)據(jù)庫表的字段揭措。

  2. 使用WCDB_IMPLEMENTATIO宏在類文件定義綁定到數(shù)據(jù)庫表的類。

  3. 使用WCDB_SYNTHESIZE宏在類文件定義需要綁定到數(shù)據(jù)庫表的字段躬充。

簡單幾行代碼以政,就完成了將類和需要的字段綁定到數(shù)據(jù)庫表的過程。這三個(gè)宏在名稱和使用習(xí)慣上抖誉,也都和定義一個(gè)ObjC類相似樊零,以此便于記憶。

除此之外塑悼,WCDB還提供了許多可選的宏烹植,用于定義數(shù)據(jù)庫索引草雕、約束等嘱巾,如:

  1. WCDB_PRIMARY用于定義主鍵

  2. WCDB_INDEX用于定義索引

  3. WCDB_UNIQUE用于定義唯一約束

  4. WCDB_NOT_NULL用于定義非空約束

具體用法

在我們的項(xiàng)目中,定義好的接口(SEEDDBManagerProtocol) 可以滿足一般場景的增刪改查绪杏。

#import <WCDB/WCDB.h>

@protocol SEEDDBManagerProtocol<NSObject>

@required

//便利構(gòu)造器
+ (instancetype)shareManager;


#pragma mark -- create table
/// 創(chuàng)建具體的表
/// @param tableName     表名
/// @param modelClass   對應(yīng)的model的類
- (BOOL)createTableWithName:(NSString *)tableName
                 modelClass:(Class)modelClass;


@optional

#pragma mark -- insert

/// 在某個(gè)已知的表里或油,插入新單個(gè)數(shù)據(jù)
/// @param message        需要插入的數(shù)據(jù)
- (BOOL)insertData:(WCTObject *)message;

/// 在某個(gè)已知的表里寞忿,插入(已經(jīng)存在該數(shù)據(jù),就更新)新單個(gè)數(shù)據(jù)
/// @param message        需要插入的數(shù)據(jù)
- (BOOL)insertOrReplaceObject:(WCTObject *)message;

/// 在某個(gè)表里顶岸,插入單個(gè)數(shù)據(jù)
/// @param message        需要插入的數(shù)據(jù)
/// @param tableName    表名
/// @param modelClass  對應(yīng)model的類名
- (BOOL)insertData:(WCTObject *)message
     withTableName:(NSString *)tableName
        modelClass:(Class)modelClass;

/// 在某個(gè)表里腔彰,插入(已經(jīng)存在該數(shù)據(jù),就更新)單個(gè)數(shù)據(jù)
/// @param message        需要插入的數(shù)據(jù)
/// @param tableName    表名
/// @param modelClass  對應(yīng)model的類名
- (BOOL)insertOrReplaceObject:(WCTObject *)message
                withTableName:(NSString *)tableName
                   modelClass:(Class)modelClass;



#pragma mark -- update

/// 在某個(gè)已知的表里辖佣,更新草稿數(shù)據(jù)
/// @param message        需要更新的數(shù)據(jù)
- (BOOL)updateData:(WCTObject *)message;

/// 在某個(gè)表里霹抛,更新單個(gè)數(shù)據(jù)
/// @param tableName    表名
/// @param property      需要更新的屬性
/// @param value            對應(yīng)的值
- (BOOL)updateAllRowsInTable:(NSString *)tableName
                  onProperty:(const WCTProperty &)property
                   withValue:(WCTValue *)value;;



#pragma mark -- select
/// 在某個(gè)已知的表里,根據(jù)條件獲取某個(gè)單獨(dú)的草稿數(shù)據(jù)
/// @param where        條件
- (WCTObject *)selectData:(const WCTCondition &)where;

/// 在某個(gè)表里卷谈,根據(jù)條件獲取某個(gè)單獨(dú)的草稿數(shù)據(jù)
/// @param where             條件
/// @param tableName    表名
/// @param modelClass  對應(yīng)model的類
- (WCTObject *)selectData:(const WCTCondition &)where
            withTableName:(NSString *)tableName
               modelClass:(Class)modelClass;



#pragma mark -- delete
/// 在某個(gè)已知的表里杯拐,刪除某個(gè)數(shù)據(jù)
/// @param where        條件
- (BOOL)delegateData:(const WCTCondition &)where;

/// 在某個(gè)已知的表里,刪除某個(gè)數(shù)據(jù)
/// @param where             條件
/// @param tableName    表名
/// @param modelClass  對應(yīng)model的類
- (BOOL)delegateDataWithWhere:(const WCTCondition &)where
                withTableName:(NSString *)tableName
                   modelClass:(Class)modelClass;


/**
    未完待續(xù)......
 */
@end

創(chuàng)建數(shù)據(jù)庫

#define kDataBaseFileName @"SEEDDB.sqlite"
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    static SEEDDBManager *_instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (_instance == nil) {
            _instance = [super allocWithZone:zone];
            [_instance creatDatabase];
        }
    });
    return _instance;
}

+ (instancetype)shareManager {
    return [[self alloc] init];
}
//創(chuàng)建數(shù)據(jù)庫
- (BOOL)creatDatabase{
    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *dbPath = [documentPath stringByAppendingString:kDataBaseFileName];
    self.database = [[WCTDatabase alloc] initWithPath:dbPath];
    self.database.tag = 0;
    if ([self.database canOpen]) {
        NSLog(@"創(chuàng)建數(shù)據(jù)庫成功");
    }else{
        NSLog(@"創(chuàng)建數(shù)據(jù)庫失敗");
        return NO;
    }
    
    return YES;
}

創(chuàng)建具體的表

//創(chuàng)建具體的表
- (BOOL) createTableWithName:(NSString *)tableName modelClass:(Class)modelClass{
    //創(chuàng)建表  注:該接口使用的是IF NOT EXISTS的SQL世蔗,因此可以用重復(fù)調(diào)用端逼。不需要在每次調(diào)用前判斷表或索引是否已經(jīng)存在。
    BOOL result = [self.database createTableAndIndexesOfName:tableName withClass:modelClass];
    
    if (!result) {
        NSLog(@"創(chuàng)建表失敗");
        return NO;
    }
    NSLog(@"創(chuàng)建表成功");
    return YES;
}

創(chuàng)建SEEDDBManager 的分類污淋,來跟具體業(yè)務(wù)綁定顶滩。

#define kTable_Name @"TableName"
@implementation SEEDDBManager (businessOne)

/// 在某個(gè)已知的表里,插入(已經(jīng)存在該數(shù)據(jù)寸爆,就更新)新單個(gè)數(shù)據(jù)
/// @param message        需要插入的數(shù)據(jù)
- (BOOL)insertOrReplaceObject:(Draft1 *)message{
    BOOL result = [self.database insertOrReplaceObject:message into:kTable_Name];
    
    //關(guān)閉數(shù)據(jù)庫,_database如果能自己釋放的話,會(huì)自動(dòng)關(guān)閉,就不用手動(dòng)調(diào)用關(guān)閉了
    [self.database close];
    if (!result) {
        NSLog(@"插入失敗");
        return NO;
    }else{
        NSLog(@"插入成功");
        return YES;
    }
}


/// 在某個(gè)已知的表里礁鲁,根據(jù)條件獲取某個(gè)單獨(dú)的草稿數(shù)據(jù)
/// @param where        條件
- (WCTObject *)selectData:(const WCTCondition &)where{

    WCTTable *table = [self.database getTableOfName:kTable_Name withClass:Draft1.class];
    WCTObject *objc = [ table getOneObjectWhere:where];
    return objc;
}

/// 在某個(gè)已知的表里,刪除某個(gè)數(shù)據(jù)
/// @param message        需要插入的數(shù)據(jù)
- (BOOL)delegateData:(Draft1 *)message{
    //刪除
    //DELETE FROM message WHERE localID>0;
    BOOL result = [self.database deleteObjectsFromTable:kTable_Name
                                             where:Draft1.localID == message.localID];
    
    return result;
}

這樣可以使用全局統(tǒng)一的SEEDDBManager單利對象來調(diào)用數(shù)據(jù)庫方法赁豆。 具體的業(yè)務(wù)代碼則由各自SEEDDBManager的分類管理仅醇。

關(guān)于model的嵌套

在業(yè)務(wù)場景中,很容易遇到在Draft1模型的內(nèi)部包含有一個(gè)其他的model魔种。
不做任何處理的話析二,是沒法正常使用的。
WCDB提供了一些具體的類型和方法如下:


WCDB1.png
WCDB2.png

需要在內(nèi)部嵌套的model類节预,做一些處理甲抖。 需要實(shí)現(xiàn)

  • (id)columnTypeForWCDB:
  • (instancetype)unarchiveWithWCTValue:(WCTValue *)value;
  • (id)archivedWCTValue;
    這三個(gè)方法。

創(chuàng)建DetailModel

.h
#import <WCDB/WCDB.h>

@interface DetailModel : NSObject<WCTColumnCoding,WCTTableCoding,NSCoding>

@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *content;

WCDB_PROPERTY(title)
WCDB_PROPERTY(content)

@end


. mm
@implementation DetailModel

WCDB_IMPLEMENTATION(DetailModel)

WCDB_SYNTHESIZE(DetailModel, title)
WCDB_SYNTHESIZE(DetailModel, content)

- (id)archivedWCTValue {
    return [NSKeyedArchiver archivedDataWithRootObject:self];;
}

+ (WCTColumnType)columnTypeForWCDB {
    return WCTColumnTypeBinary;
}

+ (instancetype)unarchiveWithWCTValue:(WCTValue *)value {
    if (value) {
        @try {
            DetailModel *model =  [NSKeyedUnarchiver unarchiveObjectWithData:value];
            return model;
        }
        @catch (NSException *exception) {
            NSLog(@"exception:%@",[exception description]);
        }
    }
    return nil;
}

//歸檔
- (void)encodeWithCoder:(NSCoder *)aCoder{
    unsigned int outCount = 0;
    Ivar *ivars = class_copyIvarList([self class], &outCount);
    for (unsigned int i =0; i<outCount; i++) {
        Ivar ivar = ivars[i];
        NSString*key = [NSString stringWithUTF8String:ivar_getName(ivar)];
        
        id value = [self valueForKey:key];
        [aCoder encodeObject:value forKey:key];
    }
    free(ivars);
}

//解歸檔
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
        unsigned int OutCount = 0;
        Ivar *ivars = class_copyIvarList([self class], &OutCount);
        for (unsigned int i =0; i<OutCount; i++) {
            Ivar ivar = ivars[i];
            NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
            [self setValue:[aDecoder decodeObjectForKey:key] forKey:key];
        }
        free(ivars);
    }
    return  self;
}

@end

這樣就可以model嵌套了心铃。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末准谚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子去扣,更是在濱河造成了極大的恐慌柱衔,老刑警劉巖樊破,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異唆铐,居然都是意外死亡哲戚,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門艾岂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來顺少,“玉大人,你說我怎么就攤上這事王浴〈嘌祝” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵氓辣,是天一觀的道長秒裕。 經(jīng)常有香客問我,道長钞啸,這世上最難降的妖魔是什么几蜻? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮体斩,結(jié)果婚禮上梭稚,老公的妹妹穿的比我還像新娘。我一直安慰自己絮吵,他們只是感情好弧烤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著源武,像睡著了一般。 火紅的嫁衣襯著肌膚如雪想幻。 梳的紋絲不亂的頭發(fā)上粱栖,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音脏毯,去河邊找鬼闹究。 笑死,一個(gè)胖子當(dāng)著我的面吹牛食店,可吹牛的內(nèi)容都是我干的渣淤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吉嫩,長吁一口氣:“原來是場噩夢啊……” “哼价认!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起自娩,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤用踩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脐彩,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碎乃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惠奸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梅誓。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖佛南,靈堂內(nèi)的尸體忽然破棺而出梗掰,到底是詐尸還是另有隱情,我是刑警寧澤共虑,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布愧怜,位于F島的核電站,受9級(jí)特大地震影響妈拌,放射性物質(zhì)發(fā)生泄漏拥坛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一尘分、第九天 我趴在偏房一處隱蔽的房頂上張望猜惋。 院中可真熱鬧,春花似錦培愁、人聲如沸著摔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谍咆。三九已至,卻和暖如春私股,著一層夾襖步出監(jiān)牢的瞬間摹察,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工倡鲸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留供嚎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓峭状,卻偏偏與公主長得像克滴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子优床,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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

  • @[TOC](IOS DB技術(shù)框架對比) 1. 數(shù)據(jù)庫簡介 目前移動(dòng)端數(shù)據(jù)庫方案按其實(shí)現(xiàn)可分為兩類: 關(guān)系型數(shù)據(jù)庫...
    孔雨露閱讀 585評論 0 5
  • 基本特性 易用劝赔,WCDB支持一句代碼即可將數(shù)據(jù)取出并組合為object。 WINQ(WCDB語言集成查詢):通過W...
    AKyS佐毅閱讀 15,903評論 7 30
  • 前言 移動(dòng)端的數(shù)據(jù)庫選型一直是一個(gè)難題胆敞,直到前段時(shí)間看到了WeMobileDev(微信前端團(tuán)隊(duì))放出了第三個(gè)開源組...
    上冬十二閱讀 3,108評論 1 5
  • 前言 WCDB是微信移動(dòng)端團(tuán)隊(duì)開源的移動(dòng)端數(shù)據(jù)庫組件望忆,提供了一個(gè)高效罩阵、完整、易用的移動(dòng)端存儲(chǔ)方案启摄。第一次應(yīng)用到WC...
    沙琪瑪dd閱讀 21,614評論 3 18
  • 第一章 2 續(xù) 晨光熹微稿壁。潮濕的霧氣籠著蓮坂菜市場。市井百態(tài)間歉备,有推著車賣早餐的小販傅是,有賣海鮮趕早市的漁民,又有媽...
    尤婆姨lilly閱讀 177評論 0 2