iOS Kingdom — 模型信息輸出

Mouse
在 iOS 開發中,相信有很多程序員都會遇到過這種事情 —— 當你用 NSLog 打印一個 NSArrayNSDictionary 時,當數組或字典中有自定義類時,控制臺只會輸出這個類的類名加上其內存地址,如下圖:
模型名稱和內存地址
如果我們要看其中某個元素的某個屬性值,則需要將這個元素取出來,然后再輸出對應的元素值,大致代碼如下:
// model0 model1 是 WQModel 的兩個實例
NSArray *arr = @[model0, model1];
WQModel *model = arr[0];
NSLog(@"name = %@",model.name);
然而這幾句代碼在實際中的作用是查看 modelname 的值,對你的業務邏輯沒有什么實質性的貢獻。如果我們能在打印數組元素時就可以看到其元素中屬性的值則可以少寫一些代碼,又可以更直觀的看出其內容,如下圖:
模型內容輸出
要實現 圖:模型內容輸出 的日志打印形式,首先須要清楚這幾個函數:
-description :當你輸出一個對象時會調用該函數,如:NSLog(@"%@",model);
-debugDescription :當你在使用 LLDB 在控制臺輸入 po model 時會調用該函數
-descriptionWithLocale:indent: :存在于 NSArrayNSDictionary 等類中。當類中有這個函數時,它的優先級為 -descriptionWithLocale:indent: > -description

1、NSObject+WQModelNSObjectDescription 函數實現

重寫 -description-debugDescription,返回對象的輸出描述
- (NSString *)description {
    return [self modelDescriptionWithIndent:0];
}

- (NSString *)debugDescription {
    return [self modelDescriptionWithIndent:0];
}

- (NSString *)modelDescriptionWithIndent:(NSInteger)level {
    uint count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    NSMutableString *mStr = [NSMutableString string];
    NSMutableString *tab = [NSMutableString stringWithString:@""];
    for (int index = 0; index < level; index ++) {
        [tab appendString:@"\t"];
    }
    [mStr appendString:@"{\n"];
    for (int index = 0; index < count; index ++) {
        NSString *lastSymbol = index + 1 == count ? @"" : @";";
        objc_property_t property = properties[index];
        NSString *name = @(property_getName(property));
        id value = [self valueForKey:name];
        [self dictionaryFormatWithMStr:mStr
                                   tab:tab
                                  name:name
                                 value:value
                            lastSymbol:lastSymbol
                                indent:level];
    }
    [mStr appendFormat:@"%@}",tab];
    free(properties);
    return [NSString stringWithFormat:@"<%@ : %p> %@",
            NSStringFromClass([self class]),
            self,
            mStr];
}

// 定義字典輸出格式
- (void)dictionaryFormatWithMStr:(NSMutableString *)mStr
                             tab:(NSMutableString *)tab
                            name:(id)name
                           value:(id)value
                      lastSymbol:(NSString *)lastSymbol
                          indent:(NSInteger)level{
    if ([NSBundle bundleForClass:[value class]] == [NSBundle mainBundle]) {
        // 自定義類
        if ([value respondsToSelector:@selector(modelDescriptionWithIndent:)]) {
            [mStr appendFormat:@"\t%@%@ = %@%@\n",
             tab,
             name,
             [value modelDescriptionWithIndent:level + 1],
             lastSymbol];
            return;
        }
    }else {
        // 系統類
        if ([value respondsToSelector:@selector(descriptionWithLocale:indent:)]) {
            [mStr appendFormat:@"\t%@%@ = %@%@\n",
             tab,
             name,
             [value descriptionWithLocale:[NSLocale systemLocale]
                                   indent:level + 1],
             lastSymbol];
            return;
        }
    }
    [mStr appendFormat:@"\t%@%@ = %@%@\n",
     tab,
     name,
     value,
     lastSymbol];
}

// 定義數組輸出格式
- (void)arrayFormatWithMStr:(NSMutableString *)mStr
                        tab:(NSMutableString *)tab
                      value:(id)value
                 lastSymbol:(NSString *)lastSymbol
                     indent:(NSInteger)level {
    if ([NSBundle bundleForClass:[value class]] == [NSBundle mainBundle]) {
        // 自定義類
        if ([value respondsToSelector:@selector(modelDescriptionWithIndent:)]) {
            [mStr appendFormat:@"\t%@%@%@\n",
             tab,
             [value modelDescriptionWithIndent:level + 1],
             lastSymbol];
            return;
        }
    }else {
        // 系統類
        if ([value respondsToSelector:@selector(descriptionWithLocale:indent:)]) {
            [mStr appendFormat:@"\t%@%@%@\n",
             tab,
             [value descriptionWithLocale:[NSLocale systemLocale]
                                   indent:level + 1],
             lastSymbol];
            return;
        }
    }
    [mStr appendFormat:@"\t%@%@%@\n",
     tab,
     value,
     lastSymbol];
}

2、NSObject+WQModelNSArrayDescription 函數實現

重寫 -descriptionWithLocale:indent:-debugDescription,返回對象的輸出描述
- (NSString *)descriptionWithLocale:(id)locale
                             indent:(NSUInteger)level {
    NSMutableString *mStr = [NSMutableString string];
    NSMutableString *tab = [NSMutableString stringWithString:@""];
    for (int index = 0; index < level; index ++) {
        [tab appendString:@"\t"];
    }
    [mStr appendString:@"(\n"];
    for (int index = 0; index < self.count; index ++) {
        NSString *lastSymbol = (self.count == index + 1) ? @"":@",";
        id value = self[index];
        [self arrayFormatWithMStr:mStr
                              tab:tab
                            value:value
                       lastSymbol:lastSymbol
                           indent:level];
    }
    [mStr appendFormat:@"%@)",tab];
    return mStr;
}

- (NSString *)debugDescription {
    return [self descriptionWithLocale:[NSLocale systemLocale]];
}

3、NSObject+WQModelNSDictionaryDescription 函數實現

重寫 -descriptionWithLocale:indent:-debugDescription,返回對象的輸出描述
- (NSString *)descriptionWithLocale:(id)locale
                             indent:(NSUInteger)level {
    NSMutableString *mStr = [NSMutableString string];
    NSMutableString *tab = [NSMutableString stringWithString:@""];
    for (int index = 0; index < level; index++) {
        [tab appendString:@"\t"];
    }
    [mStr appendString:@"{\n"];
    NSArray *allKey = self.allKeys;
    for (int index = 0; index < allKey.count; index++) {
        id value = self[allKey[index]];
        NSString *lastSymbol = (allKey.count == index + 1) ? @"":@";";
        [self dictionaryFormatWithMStr:mStr
                                   tab:tab
                                  name:allKey[index]
                                 value:value
                            lastSymbol:lastSymbol
                                indent:level];
    }
    [mStr appendFormat:@"%@}",tab];
    return mStr;
}

- (NSString *)debugDescription {
    return [self descriptionWithLocale:[NSLocale systemLocale]];
}

4、NSObject+WQModelNSSetDescription 函數實現

重寫 -descriptionWithLocale:indent:-debugDescription,返回對象的輸出描述
- (NSString *)descriptionWithLocale:(id)locale
                             indent:(NSUInteger)level {
    NSMutableString *mStr = [NSMutableString string];
    NSMutableString *tab = [NSMutableString stringWithString:@""];
    for (int index = 0; index <level; index ++) {
        [tab appendString:@"\t"];
    }
    [mStr appendString:@"{(\n"];
    for (id value in [self allObjects]) {
        NSString *lastSymbol = [value isEqual:[[self allObjects] lastObject]] ? @"" : @",";
        [self arrayFormatWithMStr:mStr
                              tab:tab
                            value:value
                       lastSymbol:lastSymbol
                           indent:level];
    }
    [mStr appendFormat:@"%@)}",tab];
    return mStr;
}

- (NSString *)debugDescription {
    return [self descriptionWithLocale:[NSLocale systemLocale]];
}
Github 示例 : https://github.com/AppleDP/WQModelDescription
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內容

  • 這篇文章完全是基于南峰子老師博客的轉載 這篇文章完全是基于南峰子老師博客的轉載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,578評論 33 466
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,722評論 18 399
  • 古有琴師伯牙在鐘子期死后,摔琴絕弦,終身不彈,故有高山流水之曲。而今,朋友之間卻因意見相左而分道揚鑣!既然圈子...
    清泠若馨閱讀 564評論 2 1
  • 從小到大聽媽媽說的最多的話,便是在家靠父母,出門靠朋友。的確我也對這句話深信不疑,所以即便是在學校我也要努力維持和...
    譚譚ne閱讀 250評論 0 1