使用的runtime的一個小工具

weixin_34236497發表於2015-11-20

1.iOS系統本身沒有提供獲取一個類所有屬性的功能,如果你跟我一樣經常使用字典來物件賦值,就會碰到煩人的“this class is not key value coding-compliant for the key xxx”;如果可以提前判斷這個物件是否有這個屬性,就可以避免這個崩潰了。

-(NSArray *)property_names{
    unsigned int outCount;
    objc_property_t *properties = class_copyPropertyList([self class], &outCount);
    
    NSMutableArray* props = [NSMutableArray array];
    for (int i = 0; i< outCount; i++) {
        objc_property_t property = properties[i];
        const char* char_f =property_getName(property);
        NSString *propertyName = [NSString stringWithUTF8String:char_f];
        
        [props addObject:propertyName];
    }
    
    free(properties);
    return props;
}

給NSObject新增一個category,然後加上這個方法,就可以獲取任意物件的屬性列表了。

2.有時候,不僅想得到所有的屬性名,我還想得到對應的屬性值,也就是把一個物件轉成字典來表示,怎麼辦?只要在上面的基礎上做稍許的改動

/* 獲取物件的所有屬性 */
- (NSDictionary *)properties_aps
{
    NSMutableDictionary *props = [NSMutableDictionary dictionary];
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList([self class], &outCount);
    for (i = 0; i<outCount; i++)
    {
        objc_property_t property = properties[i];
        const char* char_f =property_getName(property);
        NSString *propertyName = [NSString stringWithUTF8String:char_f];
      //把對應的值也取出來
        id propertyValue = [self valueForKey:(NSString *)propertyName];
        if (propertyValue) [props setObject:propertyValue forKey:propertyName];
    }
    free(properties);
    return props;
}

可能很多人沒有這種需求,我是因為:要經常的使用類似的控制元件在許多不同的專案裡-->所以把這些控制元件抽象出來,通過一些引數來調控-->當引數多了就把引數用json的格式組織起來,因為可能有好多層,比如A介面是一個tableView、每個cell進去是一個collectionView,然後collectionView的cell點選進去還有東西,而這些一連串的介面可能都是通用的控制元件,那從一開始傳遞的引數就需要是多層的了-->所以就需要json、NSDictionary、物件的相互轉化。

有了上面的方法,物件可以轉成字典,而通過

//使用字串構建物件
Class class = NSClassFromString("classname");
    id target = [[class alloc]init];
//使用字典給物件賦值
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;

來賦值物件;

字典和json轉就簡單了,系統有提供方法。打通了物件到字串的通道,而字串可以通過網路介面獲得,那麼可以像web一樣,從後臺獲取配置資訊(字串),然後轉成物件,本地介面、操作根據這些來變化。就可以達到極大的便利。


一點思考:
一開始的目的只是“把通用的控制元件抽象出來”,後來越寫越感覺像web,引數多了->寫成json格式檔案,這TM不就是指令碼嗎?如果我實現了巨多的控制元件型別,並且也發明了一套完整的規則來:告訴你怎麼寫會得到什麼樣的介面以及這些介面怎麼互動。這不就是瀏覽器嗎?

只是我現在做的專案只是某個很小範圍的,也沒能力去做完整的解決方案,只是這種思路是ok的,想要包羅永珍,那配置檔案也會變得相當複雜,但是如果是自己特定領域的專案,可以做一套簡單、但更具適應性的解決方案:達到使用配置檔案(json\xml或其他指令碼檔案甚至自己定義解析方式的檔案)通過網路來控制介面,甚至可以每個使用者登入後,根據他的屬性配置一套定製的介面。

這會不會比使用�已有的web+native的解決方案更好呢,畢竟這樣還更契合自己的專案。

其實APP介面就那麼些,隨著時間推移,每一種都會出現足夠完美的樣式,在我要求不高的時候,是不是可以拿來用就是,不用寫swift或OC程式碼,用指令碼把這些控制元件串起來就行了。

相關文章