EasyDataKit 簡單易用的 SQLite 輪子
EasyDataKit 是一個基于 FMDB 封裝的庫,它可以免去開發者編寫復雜 SQL 的困擾,更加專注業務上的事情,從而提高開發效率。
特征
- 類 ORM 接口
- 自動創建庫和表,支持表新增字段的修改
- 支持 where 查詢語句
- 自動事務提升插入效率
使用
EasyDataKit 適用于將網絡請求的數據持久化到數據庫中,特別是處理網絡請求數據時不習慣把數據轉換成 model。筆者的淺見是:轉換對性能是有消耗的,獲得的可讀性好處也可以通過字符串常量解決。
假設你通過網絡請求獲取到了數據:
{
"data": {
"id": "56d177a27cb3331100465f72",
"messagePrefix": "飯否每日精選",
"content": "飯否每日精選",
"topicId": 1345,
"briefIntro": "飯否是國內著名的小眾輕博客社區,氛圍獨特,清新自由。關注飯否每日精選,看看塵囂之外,大家談論什么。",
"keywords": "飯否 精選 短博客 社區",
"timeForRank": "2016-02-27T11:06:30.731Z",
"lastMessagePostTime": "2016-11-06T02:42:52.111Z",
"topicPublishDate": "2016-02-26T16:00:00.000Z",
"createdAt": "2016-02-27T10:17:06.295Z",
"updatedAt": "2016-11-01T04:30:08.973Z",
"subscribersCount": 1207100,
"subscribedStatusRawValue": 1,
"subscribedAt": "2016-10-18T09:57:24.424Z",
"rectanglePicture": {
"thumbnailUrl": "https://cdn.ruguoapp.com/o_1ach3c6o011j91ljjtmdhlhnffo.jpg?imageView2/1/w/120/h/180",
"middlePicUrl": "https://cdn.ruguoapp.com/o_1ach3c6o011j91ljjtmdhlhnffo.jpg?imageView2/1/w/200/h/300",
"picUrl": "https://cdn.ruguoapp.com/o_1ach3c6o011j91ljjtmdhlhnffo.jpg?imageView2/0/h/1000",
"format": "png"
},
"squarePicture": {
"thumbnailUrl": "https://cdn.ruguoapp.com/o_1ach6nm599m94re1gvj14r71jaso.jpg?imageView2/0/w/120/h/120",
"middlePicUrl": "https://cdn.ruguoapp.com/o_1ach6nm599m94re1gvj14r71jaso.jpg?imageView2/0/w/300/h/300",
"picUrl": "https://cdn.ruguoapp.com/o_1ach6nm599m94re1gvj14r71jaso.jpg?imageView2/0/h/1000",
"format": "png"
},
"pictureUrl": "https://cdn.ruguoapp.com/o_1ach3c6o011j91ljjtmdhlhnffo.jpg?imageView2/1/w/200/h/300",
"thumbnailUrl": "https://cdn.ruguoapp.com/o_1ach6nm599m94re1gvj14r71jaso.jpg?imageView2/0/w/300/h/300"
}
}
你可將這段 JSON String 轉換成 Dictionary 或 Array:
NSDictionary *dictionary = [NSJSONSerializationJSONObjectWithData:dataoptions:NSJSONReadingAllowFragmentserror:nil];
NSDictionary *subscribe = dictionary[@"data"];
接著便可使用 EasyDataKit 的 API 進行存儲:
EDKEntity *subscribeEntity = [[EDKEntity alloc]initWithTableName:@"subcribes"dbName:nil];
[subscribeEntitysaveData:subscribeprimaryColumn:@"id"relationShip:nilindexes:nil];
可以手動為數據添加列,實現滿足業務的需求:
NSMutableDictionary *subcribeInfo = [[NSMutableDictionary alloc]initWithDictionary:subscribe];
[subcribeInfosetObject:<a ];
EDKEntity *subscribeEntity = [[EDKEntity alloc]initWithTableName:@"subcribes"dbName:nil]; [subscribeEntitysaveData:subcribeInfoprimaryColumn:@"id"relationShip:nilindexes:nil];
如果你想讓某紀錄關聯其它對象,可以將對象存儲后返回的 id 作為 value,key 是該紀錄原本對應該對象的字段,這相當于用 id 這個值去替換原本字段對應的對象,從而達到拆分的目的:
id rowId = [rectanglePictureEntitysaveData:subscribe[@"rectanglePicture"]primaryColumn:nilrelationShip:nil];
EDKEntity *subscribeEntity = [[EDKEntity alloc]initWithTableName:@"subcribes"dbName:nil];
[subscribeEntitysaveData:subscribeprimaryColumn:@"id"relationShip:@{@"rectanglePicture": rowId}indexes:nil];
EasyDataKit 還可以存儲索引
NSDictionary *subcribeInfo = [[NSDictionary alloc]initWithDictionary:subscribe];
EDKEntity *subscribeEntity = [[EDKEntity alloc]initWithTableName:@"subcribes"dbName:@"TestIndex"];
[subscribeEntitysaveData:subcribeInfoprimaryColumn:nilrelationShip:nilindexes:@[@[@"topicId"], @[@"content", @"messagePrefix"]]];
對存儲來說,EasyDataKit 還提供了自動 ALTER TABLE 添加列的功能,方便開發者應對升級,原理是當檢測到待存儲的字典 keys 數組元素個數比之前已經在表中的列多時,則會自動為表添加新的列,即并不支持修改列和刪除列的操作,而 EasyDataKit 對創建的索引是支持修改刪除的。
查詢:
// select by id
EDKEntity *entity = [[EDKEntity alloc]initWithTableName:@"messages"dbName:nil];
id object = [entityqueryByPrimaryKey:@"581d2fdb36a4471100e311d6"withColumns:@[@"topicId", @"commentCount", @"topic"]];
NSLog(@"%@", object);
NSArray *objects = [entityqueryWithColumns:nilwhere:@"WHERE commentCount < ? and read = ?"arguments:@[@20, @1]];
NSLog(@"%@", objects);
查詢嵌套對象并將其轉換為 Dictionary 或 Array:
EDKEntity *subcribeEntity = [[EDKEntity alloc]initWithTableName:@"subcribes"dbName:nil];
// select by id id
subcribe = [subcribeEntityqueryByPrimaryKey:@"56d177a27cb3331100465f72"withColumns:@[@"squarePicture"]];
// subcribe is a json string
NSData *data = [subcribe[@"squarePicture"]dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSDictionary *jsonDict = [NSJSONSerializationJSONObjectWithData:dataoptions:0error:&error];
NSLog(@"JSONDict: %@", jsonDict);
更新:
EDKEntity *entity = [[EDKEntity alloc]initWithTableName:@"messages"dbName:nil];
[entityupdateByPrimaryKey:@"5805905a319a9c1200833660"set:@{@"read": @"0", @"commentCount": @99}];
[entityupdateWithSet:@{@"messageId": @"2333333"}where:@"WHERE commentCount > ?"arguments:@[@50]];
刪除:
EDKEntity *entity = [[EDKEntity alloc]initWithTableName:@"messages"dbName:nil];
// delete by id
[entitydeleteByPrimaryKey:@"5805905a319a9c1200833660"];
// delete by where
[entitydeleteWithWhere:@"WHERE popularity = ?"arguments:@[@"93"]];
// delete all
[entitydeleteAll];
EDKEntity *entity = [[EDKEntity alloc]initWithTableName:@"messages"dbName:nil];
// delete by id
[entitydeleteByPrimaryKey:@"5805905a319a9c1200833660"];
// delete by where
[entitydeleteWithWhere:@"WHERE popularity = ?"arguments:@[@"93"]];
// delete all
[entitydeleteAll];
由上面可以看出,只要創建出 EDKEntity 對象,就可以輕松加愉快地進行存儲,查找,修改,刪除操作。開發者無需創建數據庫、表,EasyDataKit 也支持 db 的劃分,但不提供內存緩存,原因是筆者認為沒有熱塊的數據庫緩存意義不是太大。當有寫操作發生的時候,EasyDataKit 會通過輪詢的事務機制打包寫操作,從而提高頻繁寫操作的效率。(更詳細的使用請移步 EasyDataKit 中的 Example)
源碼簡析
EasyDataKit 有個 swizzle 了 NSMutableDictionary 的 setObject:forKey: 和 NSMutableArray 的 addObject:,使得應對空值不會 crash。
EasyDataKit 還有個遞歸方法:dealWithObject:,主要有兩個用途:一是用來檢測除了 NSDictionary、NSArray、NSString、NSNumber、NSNull 這些類型以外的合法性,譬如 UIView 類型直接調用 description 轉換成字符串;二是為了能讓嵌套的 Dictionary 或 Array 以 JSON String 的形式存入數據庫,在取出后仍可以將其轉換回 Dictionary 或 Array。
DISPATCH_SOURCE_TYPE_TIMER 創建的定時器。
來自:http://ios.jobbole.com/90509/