1. 引言
在iOS開發(fā)調(diào)試過程中摩钙,打印日志是最常使用的手段,但是打印日志有時候無法提供詳細(xì)的信息用于問題的分析,?例如一般的消息數(shù)據(jù)由于數(shù)據(jù)量較大响禽,打印日志時只會選擇將一些關(guān)鍵信息打印出來,信息不夠完整。因此芋类,如果能將存入sqlite數(shù)據(jù)庫中的數(shù)據(jù)導(dǎo)出隆嗅,對于問題的分析定位解決?將會十分有幫助。
2. python解析sqlite基本數(shù)據(jù)類型[1]
2.1 數(shù)據(jù)庫基本操作
- 數(shù)據(jù)庫連接
import sqlite3
conn = sqlite3.connect('example.db')
- 數(shù)據(jù)庫連接對象基本操作
cur = conn.cursor() //創(chuàng)建cursor
conn.commit() //事務(wù)提交
conn.rollback() //事務(wù)回滾
conn.close() //關(guān)閉一個數(shù)據(jù)庫鏈接
- 數(shù)據(jù)庫cursor基本操作
cur.execute() //執(zhí)行sql語句
cur.fetchone() //從結(jié)果中取出一條記錄
cur.fetchall() //從結(jié)果中取出所有記錄
cur.close() //關(guān)閉cursor
2.2 獲取數(shù)據(jù)庫中的表
sqlite數(shù)據(jù)庫中都包含一個特殊的表sqlite_master侯繁,其表結(jié)構(gòu)為:
CREATE TABLE sqlite_master (
type TEXT,
name TEXT,
tbl_name TEXT,
rootpage INTEGER,
sql TEXT);
可以利用此表來查詢數(shù)據(jù)庫中所有的表:
tables = cur.execute("select name from sqlite_master where type = 'table' order by name").fetchall()
2.3 獲取表結(jié)構(gòu)
columns = cur.execute("PRAGMA table_info(%s)" % table).fetchall()
2.4 獲取表中的數(shù)據(jù)
data = cur.execute("select * from %s" % table).fetchall()
3. iOS序列化存儲
在iOS開發(fā)中胖喳,經(jīng)常將可能會擴(kuò)展或者根據(jù)不同類型存儲不同數(shù)據(jù)的數(shù)據(jù)庫字段定義為blob類型,采用NSKeyedArchiver
對具有差異性的數(shù)據(jù)進(jìn)行序列化贮竟,轉(zhuǎn)為NSData數(shù)據(jù)進(jìn)行存儲丽焊。
例如消息的數(shù)據(jù)表結(jié)構(gòu)可定義為:
CREATE TABLE ?message (
msgId integer primary key,
msgType int,
extensionData blob);
其中extensionData就可以根據(jù)消息的類型(?例如文本、圖片咕别、多媒體等)技健,存儲不同的數(shù)據(jù);同時extensionData中的數(shù)據(jù)還可以在不改變表結(jié)構(gòu)的條件下惰拱,進(jìn)行其自身的數(shù)據(jù)擴(kuò)展雌贱。
?假設(shè)圖片消息類定義為:
@interface PicMsg : NSObject
@property (nonatomic, assign) NSUInteger msgType;
@property (nonatomic, strong) PicInfo *picInfo;
@end
其中PicInfo為圖片基本信息:
@interface PicInfo : NSObject<NSCoding>
@property (nonatomic, assign) ?NSUInteger picType;
@property (nonatomic, assign) ?NSUInteger fileSize;
@property (nonatomic, assign) ?NSUInteger picWidth;
@property (nonatomic, assign) ?NSUInteger picHeight;
@end
@implementation PicInfo
-(void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:@(self.picType) forKey:@"picType"];
[coder encodeObject:@(self.fileSize) forKey:@"fileSize"];
[coder encodeObject:@(self.picWidth) forKey:@"picWidth"];
[coder encodeObject:@(self.picHeight) forKey:@"picHeight"];
}
-(id)initWithCoder:(NSCoder *)decoder
{
if (self = [super init]) {
self.msgType = [[decoder decodeObjectForKey:@"picType"] unsignedIntegerValue];
self.fileSize = [[decoder decodeObjectForKey:@"fileSize"] unsignedIntegerValue];
self.picWidth = [[decoder decodeObjectForKey:@"picWidth"] unsignedIntegerValue];
self.picHeight = [[decoder decodeObjectForKey:@"picHeight"] unsignedIntegerValue];
}
return self;
}
@end
這樣在存入數(shù)據(jù)庫時就可以調(diào)用[NSKeyedArchiver archivedDataWithRootObject:self.picFileInfo];
,將picInfo轉(zhuǎn)化為NSData存入extensionData字段里偿短。
4. python+pyobjc[2]解析序列化數(shù)據(jù)
4.1 pyobjc
PyObjC is a bridge between Python and Objective-C. It allows full featured Cocoa applications to be written in pure Python. It is also easy to use other frameworks containing Objective-C class libraries from Python and to mix in Objective-C, C and C++ source.
在使用pyobjc和iOS相關(guān)框架時欣孤,只需要import相關(guān)模塊即可,例如Foundation框架:
from Foundation import *
4.2 pyobjc解析序列化數(shù)據(jù)
- 定義?對應(yīng)類
要對打包數(shù)據(jù)進(jìn)行解包昔逗,需要用python定義與OC相對應(yīng)的類降传。
例如第3節(jié)中提到的PicInfo
,改用python定義為:
class PicInfo(NSObject):
def init(self):
self = super(PicInfo, self).init()
if self is None:
print "init None"
return self
def initWithCoder_(self, encoder):
self = super(PicInfo, self).init()
if self is None:
print "initWithCoder_ None"
self.picType = encoder.decodeObjectForKey_("picType")
self.fileSize = encoder.decodeObjectForKey_("fileSize")
self.picWidth = encoder.decodeObjectForKey_("picWidth")
self.picHeight = encoder.decodeObjectForKey_("picHeight")
return self
def encodeWithCoder_(self, decoder):
decoder.encodeObject_forKey_(self.picType, "picType")
decoder.encodeObject_forKey_(self.fileSize, "fileSize")
decoder.encodeObject_forKey_(self.picWidth, "picWidth")
decoder.encodeObject_forKey_(self.picHeight, "picHeight")
- 數(shù)據(jù)的序列化與反序列化
picInfo = PicInfo.alloc().init()
picInfo.picType = 1
picInfo.fileSize = 1024
picInfo.picWidth = 200
picInfo.picHeight = 100
// 序列化
archivedData = NSKeyedArchiver.archivedDataWithRootObject_(picInfo)
// 反序列化
unarchivedPicInfo = NSKeyedUnarchiver.unarchiveObjectWithData_(archivedData)
5. 結(jié)語
python+pyobjc不僅僅可以在iOS開發(fā)時進(jìn)行數(shù)據(jù)的序列化和反序列化纤子,利用pyobjc可以在Mac OS上使用純python開發(fā)Cocoa GUI應(yīng)用搬瑰,功能非常強大。
參考資料
[1]sqlite3 DB-API 2.0 interface for SQLite databases
[2]pyobjc module
[3]pyobjc package documentation