西西軟件下載最安全的下載網(wǎng)站、值得信賴(lài)的軟件下載站!

首頁(yè)編程開(kāi)發(fā)其它知識(shí) → Obj-C語(yǔ)言開(kāi)發(fā)iOS項(xiàng)目使用反射減少代碼工作

Obj-C語(yǔ)言開(kāi)發(fā)iOS項(xiàng)目使用反射減少代碼工作

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:西西整理時(shí)間:2012/12/19 21:25:22字體大。A-A+

作者:西西整理點(diǎn)擊:0次評(píng)論:0次標(biāo)簽: 反射

  • 類(lèi)型:免DVD補(bǔ)丁大。2.7M語(yǔ)言:中文 評(píng)分:5.0
  • 標(biāo)簽:
立即下載

最近在一個(gè)iOS項(xiàng)目中,利用到了Obj-c語(yǔ)言的運(yùn)行時(shí)反射特性,來(lái)減少一些代碼編寫(xiě)的工作量,特記錄下來(lái)。
移動(dòng)互聯(lián)網(wǎng)下iOS客戶(hù)端的開(kāi)發(fā),一般都會(huì)與服務(wù)端進(jìn)行通訊,也會(huì)使用到Sqlite數(shù)據(jù)庫(kù)來(lái)保存一些數(shù)據(jù),按常規(guī)的搞法,一般都需要手動(dòng)建表結(jié)構(gòu),寫(xiě)實(shí)體類(lèi)對(duì)象,然后寫(xiě)插入、更新、查詢(xún)等語(yǔ)句來(lái)實(shí)現(xiàn)功能,因此想到是否有一種通用的辦法來(lái)進(jìn)行一些代碼方面的減負(fù)工作。通過(guò)這個(gè)項(xiàng)目的實(shí)踐,已經(jīng)找到了答案。

在使用這些代碼前,我們進(jìn)行了以下的約定:
1. sqlite的數(shù)據(jù)庫(kù)表名直接使用實(shí)體類(lèi)的類(lèi)名;
2. sqlite的數(shù)據(jù)字段使用實(shí)體類(lèi)的屬性名稱(chēng);
3. sqlite的數(shù)據(jù)類(lèi)型統(tǒng)一設(shè)為text(引起sqlite這種文本數(shù)據(jù)庫(kù)是動(dòng)態(tài)類(lèi)型的,存儲(chǔ)的本質(zhì)都是文本)
4. 實(shí)體類(lèi)的類(lèi)型統(tǒng)一都設(shè)為NSString

做以上的約定,只是減少使用過(guò)程中,由于類(lèi)型的不同造成不必要的麻煩,如果要支持各種類(lèi)型,需要編寫(xiě)各種判斷代碼,進(jìn)行格式的處理,有興趣的同學(xué)可以進(jìn)一步研究,呵呵。

下面介紹幾個(gè)重要的方法。

因?yàn)橛玫搅薕bj-c運(yùn)行時(shí)的相關(guān)方法,所以需要導(dǎo)入運(yùn)行時(shí)的頭文件。
#import

直接擴(kuò)展了NSObject,名稱(chēng)叫NSObject+Property,文章末尾提供文件下載。

@interface NSObject (Property)
@end

1. 利用反射取得NSObject的屬性,并存入到數(shù)組中 

- (NSArray *)getPropertyList: (Class)clazz{
u_int count;
objc_property_t *properties = class_copyPropertyList(clazz, &count);
NSMutableArray *propertyArray = [NSMutableArray arrayWithCapacity:count];

for (int i = 0; i < count ; i++)
{
const char* propertyName = property_getName(properties[i]);
[propertyArray addObject: [NSString stringWithUTF8String: propertyName]];
}
free(properties);
return propertyArray;
}

2. 根據(jù)屬性生成創(chuàng)建Sqlite表的語(yǔ)句 

- (NSString *)tableSql:(NSString *)tablename{
NSMutableString *sql = [[NSMutableString alloc] init];
NSArray *array = [self getPropertyList];
[sql appendFormat:@"create table %@ (",tablename] ;
NSInteger i = 0;
for (NSString *key in array) {
if (i>0) {
[sql appendString:@","];
}
[sql appendFormat:@"%@ text",key];
i++;
}
[sql appendString:@")"];
return sql;
}

3. 把一個(gè)實(shí)體對(duì)象,封裝成字典Dictionary  

- (NSDictionary *)convertDictionary{
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
NSArray *propertyList = [self getPropertyList];
for (NSString *key in propertyList) {
SEL selector = NSSelectorFromString(key);

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
id value = [self performSelector:selector];
#pragma clang diagnostic pop

if (value == nil) {
value = [NSNull null];
}
[dict setObject:value forKey:key];
}
return dict;
}

4. 從一個(gè)字典中還原成一個(gè)實(shí)體對(duì)象

- (void)dictionaryForObject:(NSDictionary*) dict{
for (NSString *key in [dict allKeys]) {
id value = [dict objectForKey:key];

if (value==[NSNull null]) {
continue;
}
if ([value isKindOfClass:[NSDictionary class]]) {
id subObj = [self valueForKey:key];
if (subObj)
[subObj dictionaryForObject:value];
}
else{
[self setValue:value forKeyPath:key];
}
}
}

5. 返回一個(gè)對(duì)象的類(lèi)型名稱(chēng)

- (NSString *)className{
return [NSString stringWithUTF8String:object_getClassName(self)];
}

以上是對(duì)NSObject的一個(gè)擴(kuò)展,使用了Obj-C的Category特性

以下是與數(shù)據(jù)存儲(chǔ)相關(guān),定義為DbHelper,使用FMDB庫(kù)對(duì)sqlite進(jìn)行操作

1. 把id類(lèi)型的數(shù)據(jù)對(duì)象插入到數(shù)據(jù)庫(kù)
 -(void)insertObject:(id)object{
NSString *tablename = [object className];
NSMutableString *sql = [[NSMutableString alloc] init];
NSArray *array = [object getPropertyList];
[sql appendFormat:@"insert into %@ (",tablename] ;
NSInteger i = 0;
for (NSString *key in array) {
if (i>0) {
[sql appendString:@","];
}
[sql appendFormat:@"%@",key];
i++;
}
[sql appendString:@") values ("];
NSMutableArray *arrayValue = [NSMutableArray array];
i=0;
for (NSString *key in array) {
SEL selector = NSSelectorFromString(key);

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
id value = [object performSelector:selector];
#pragma clang diagnostic pop


if (value==nil) {
value = @"";
}
[arrayValue addObject:value];
if (i>0) {
[sql appendString:@","];
}
[sql appendString:@"?"];
i++;
}
[sql appendString:@")"];
[_db executeUpdate:sql withArgumentsInArray:arrayValue];
}

2. 把字典N(xiāo)SDictionary對(duì)象插入到數(shù)據(jù)庫(kù)中
在與服務(wù)器進(jìn)行交互時(shí)候,我們一般采用Json進(jìn)行數(shù)據(jù)通訊,從服務(wù)端獲取Json字符,通過(guò)JSONKit框架,反序列化成NSDictionary對(duì)象,然后插入到數(shù)據(jù)庫(kù)

生成插入的sql語(yǔ)句

-(NSString *)createInsertSqlByDictionary:(NSDictionary *)dict tablename:(NSString *)table{

NSMutableString *sql = [[NSMutableString alloc] init];
[sql appendFormat:@"insert into %@ (",table] ;
NSInteger i = 0;
for (NSString *key in dict.allKeys) {
if (i>0) {
[sql appendString:@","];
}
[sql appendFormat:@"%@",key];
i++;
}
[sql appendString:@") values ("];
i = 0;
for (NSString *key in dict.allKeys) {
if (i>0) {
[sql appendString:@","];
}
[sql appendFormat:@":%@",key];
i++;
}
[sql appendString:@")"];
return sql;
}

把字典插入到數(shù)據(jù)庫(kù)中

-(void)insertBySql:(NSString *)sql dict:(NSDictionary *)dict{
if (sql && sql.length>0) {
[_dbQueue inDatabase:^(FMDatabase *db) {
[db executeUpdate:sql withParameterDictionary:dict];
}];
}
}

取數(shù)據(jù)

3. 從數(shù)據(jù)庫(kù)取數(shù)據(jù),封裝成成字典,然后放入到數(shù)組中

-(NSArray *)queryDbToDictionaryArray:(NSString *)tablename sql:(NSString *)sql{
FMResultSet *resultSet=[_db executeQuery:sql];
NSArray *columnArray = [self fMSetColumnArray:resultSet];
NSMutableArray *syncArray = [[NSMutableArray alloc] init];
NSString *columnName = nil;
while ([resultSet next])
{
NSMutableDictionary *syncData = [[NSMutableDictionary alloc] init];
for(int i =0;i<columnArray.count;i++)
{
columnName = [columnArray objectAtIndex:i];
NSString *columnValue = [resultSet stringForColumn: columnName];
if (columnValue==nil) {
columnValue=@"";
}
[syncData setObject:columnValue forKey:columnName];
}
[syncArray addObject:syncData];
}
if ([syncArray count]==0) {
return nil;
}

return syncArray;
}

4. 從數(shù)據(jù)庫(kù)中取數(shù)據(jù),封裝成對(duì)象,然后放入數(shù)組中

-(NSArray *)queryDbToObjectArray:(Class )clazz sql:(NSString *)sql{
FMResultSet *resultSet=[_db executeQuery:sql];
NSArray *columnArray = [self fMSetColumnArray:resultSet];
NSMutableArray *syncArray = [[NSMutableArray alloc] init];
NSString *columnName = nil;
while ([resultSet next])
{
NSObject *obj = [[clazz alloc] init];

if (obj==nil) {
continue;
}

for(int i =0;i<columnArray.count;i++)
{
columnName = [columnArray objectAtIndex:i];
NSString *columnValue = [resultSet stringForColumn: columnName];
SEL selector = NSSelectorFromString(columnName);

if ([obj respondsToSelector:selector]) {
[obj setValue:columnValue forKeyPath:columnName ];
}
}
[syncArray addObject:obj];
}
if ([syncArray count]==0) {
return nil;
}
return syncArray;
}

在數(shù)據(jù)量很大時(shí)候,考慮到性能問(wèn)題,此方法需要酌情使用。

好了,最后提供這四個(gè)文件DbHelper.h、DbHelper.m、NSObject+Property.h、NSObject+Property.m的下載。
有了這幾個(gè)東西,進(jìn)行開(kāi)發(fā)就省去了很多時(shí)間和代碼量,直接動(dòng)態(tài)生成表,從服務(wù)端接口取到數(shù)據(jù),直接插入到數(shù)據(jù)庫(kù)中保存,顯示數(shù)據(jù)時(shí),從數(shù)據(jù)庫(kù)中取出數(shù)據(jù)放入到對(duì)象數(shù)組中。

由于項(xiàng)目的保密性,不可能提供整個(gè)文件的下載,只提供了關(guān)鍵的幾個(gè)文件,同學(xué)們可以根據(jù)需要進(jìn)行擴(kuò)展和研究,也歡迎一起探討,甚至拍磚。

文件下載:http://pan.baidu.com/share/link?shareid=202843&uk=85241834

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過(guò)難過(guò)
    • 5 囧
    • 3 圍觀(guān)圍觀(guān)
    • 2 無(wú)聊無(wú)聊

    熱門(mén)評(píng)論

    最新評(píng)論

    發(fā)表評(píng)論 查看所有評(píng)論(0)

    昵稱(chēng):
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)
    推薦文章

    沒(méi)有數(shù)據(jù)