好玩的debugDescription & runtime(debug模式下調試model)

description

在開發過程中, 往往會有很多的model來裝載屬性. 而在開發期間經常會進行調試查看model里的屬性值是否正確. 那么問題來了, 在objective-c里使用NSLog("%@",model)這行代碼打印出來的卻是model的地址. 不是我們所想要的結果~! 看圖:

那么問題又來了?有沒有辦法解決這個問題尼,答案那就是有~!只需要重寫- (NSString *)description方法即可。如下代碼:

.h文件

#import <Foundation/Foundation.h>

@interface TestModel : NSObject
@property (copy,nonatomic) NSString *text;
@property (assign,nonatomic) NSInteger index;
@end

.m文件

#import "TestModel.h"

@implementation TestModel
- (NSString *)description {
    return [NSString stringWithFormat:@"text:%@--index:%zi",self.text,self.index];
}
@end

然后這時候在使用NSLog("%@",model)這行代碼就能打印我們想要的結果了。 看如下圖:

那么問題繼續來了...
**如果model里有N多個屬性尼, 可能10個, 可能20個... 難道要在description方法里一個一個寫屬性并拼接返回? 你不嫌麻煩, 我光看著都蛋疼了... 所以我們可以采用runtime技術來動態獲取屬性并返回. 如下修改后的.m文件代碼: **

修改后的.m文件

#import "TestModel.h"
#import <objc/runtime.h>//導入runtime頭文件

@implementation TestModel
- (NSString *)description {
    //初始化一個字典
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
    
    //得到當前class的所有屬性
    uint count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    
    //循環并用KVC得到每個屬性的值
    for (int i = 0; i<count; i++) {
        objc_property_t property = properties[i];
        NSString *name = @(property_getName(property));
        id value = [self valueForKey:name]?:@"nil";//默認值為nil字符串
        [dictionary setObject:value forKey:name];//裝載到字典里
    }
    
    //釋放
    free(properties);
    
    //return
    return [NSString stringWithFormat:@"<%@: %p> -- %@",[self class],self,dictionary];
}
@end

然后在打印model, 如下圖:

這里寫圖片描述

</p>
</p>

debugDescription

現在問題繼續來了..
在項目中NSLog語句往往也很多. 如果重寫description方法. 在控制臺則會打印出很多屬性. 看著就不舒服~~而且還有一個問題就是, 有時候我們其實并不需要打印model的屬性.. 那這樣重寫description方法反而適得其反了! 所有, 現在有一個解決方案就是重寫debugDescription方法


什么是debugDescription? 其實debugDescriptiondescription是一樣的效果. 只不過唯一的區別就是debugDescription是在Xcode控制臺里使用po命令的時候調用的~!


debugDescription的實現其實也就是調用了description方法而已

so, 在開發過程中并且model調試的時候, 筆者推薦重寫debugDescription方法而不是重寫description方法. 當需要打印model的屬性的時候, 在控制臺里使用po命令即可. 如下在此修改后的.m文件

#import "TestModel.h"
#import <objc/runtime.h>//導入runtime頭文件

@implementation TestModel

// 重寫debugDescription, 而不是description
- (NSString *)debugDescription {
    //聲明一個字典
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
    
    //得到當前class的所有屬性
    uint count;
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    
    //循環并用KVC得到每個屬性的值
    for (int i = 0; i<count; i++) {
        objc_property_t property = properties[i];
        NSString *name = @(property_getName(property));
        id value = [self valueForKey:name]?:@"nil";//默認值為nil字符串
        [dictionary setObject:value forKey:name];//裝載到字典里
    }
    
    //釋放
    free(properties);
    
    //return
    return [NSString stringWithFormat:@"<%@: %p> -- %@",[self class],self,dictionary];
}
@end

看如下圖, 分別使用了NSLogpo命令的打印


這里寫圖片描述

結果:

這里寫圖片描述

這就達到了我們想要的效果, 如果需要打印model的屬性, 打個斷點然后使用po命令即可

demo地址

最后,附上本文章的一個小demo示例代碼,已放在github上。
https://github.com/DemoMania/DebugDescriptionDemo

總結

  • model調試的時候, 推薦重寫debugDescription而不是description
  • 利用runtime技術動態獲取class的屬性
  • base基類里重寫debugDescription方法,隨后所有model繼承與baseModel即可。
  • 在重寫的debugDescription的方法里最好不要調用自身debugDescription([self debugDescription])
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,349評論 25 708
  • 我們常常會聽說 Objective-C 是一門動態語言,那么這個「動態」表現在哪呢?我想最主要的表現就是 Obje...
    Ethan_Struggle閱讀 2,231評論 0 7
  • 最近在面試,面試過程中問到了一些Xcode常用的調試技巧問題。平常開發過程中用的還挺順手的,但你要突然讓我說,確實...
    遠0閱讀 643評論 2 8
  • 閆秋愛上了她隔壁班的男生,在這高一上學期的期中考試后,在這個炎熱的夏季,他叫杜震,閆秋愛上他的原因很簡單,因為他會...
    清夢飛揚閱讀 1,095評論 0 3
  • 這里是溫柔的,堅硬和粗糙的圍墻里,我就躲在那,安心的看著眼前的星星。 第一,不被情緒沖昏了頭腦,像一個無頭...
    眼白閱讀 309評論 0 0