1. 程式人生 > >高效開發iOS系列(runtime篇) -- debug模式下使用po命令列印model的屬性和值(runtime + debugDescription)

高效開發iOS系列(runtime篇) -- debug模式下使用po命令列印model的屬性和值(runtime + debugDescription)

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, 如下圖:

這裡寫圖片描述

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命令即可

總結

  • model除錯的時候, 推薦重寫debugDescription而不是description
  • 利用runtime技術動態獲取class的屬性