有没有办法记录Objective-C实例的所有属性值

时间:2012-12-17 21:36:17

标签: objective-c properties nslog

我只是想知道是否有一种快速简便的方法可以将所有属性的各种值打印到日志中以进行调试。就像我想知道所有BOOL,浮点数等的值是什么。

5 个答案:

答案 0 :(得分:26)

This question似乎有你的问题的答案。

更新

我好奇并做了一个类似的事情:

//Using Xcode 4.5.2 - iOS 6 - LLDB - Automatic Reference Counting

//NSObject+logProperties.h    
@interface NSObject (logProperties)
- (void) logProperties;
@end

//NSObject+logProperties.m
#import "NSObject+logProperties.h"
#import <objc/runtime.h>

@implementation NSObject (logProperties)

- (void) logProperties {

    NSLog(@"----------------------------------------------- Properties for object %@", self);

    @autoreleasepool {
        unsigned int numberOfProperties = 0;
        objc_property_t *propertyArray = class_copyPropertyList([self class], &numberOfProperties);
        for (NSUInteger i = 0; i < numberOfProperties; i++) {
            objc_property_t property = propertyArray[i];
            NSString *name = [[NSString alloc] initWithUTF8String:property_getName(property)];
            NSLog(@"Property %@ Value: %@", name, [self valueForKey:name]);
        }
        free(propertyArray);
    }    
    NSLog(@"-----------------------------------------------");
}

@end

将其包含在您的班级中:#import "NSObject+logProperties.h"

并致电[self logProperties];给这些房产!

答案 1 :(得分:6)

目前的答案只是展示了如何为属性做到这一点。如果您希望打印出每个实例变量,您可以执行以下操作。

- (void)logAllProperties {
    unsigned int count;
    Ivar *ivars = class_copyIvarList([self class], &count);
    for (unsigned int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];

        const char *name = ivar_getName(ivar);
        const char *type = ivar_getTypeEncoding(ivar);
        ptrdiff_t offset = ivar_getOffset(ivar);

        if (strncmp(type, "i", 1) == 0) {
            int intValue = *(int*)((uintptr_t)self + offset);
            NSLog(@"%s = %i", name, intValue);
        } else if (strncmp(type, "f", 1) == 0) {
            float floatValue = *(float*)((uintptr_t)self + offset);
            NSLog(@"%s = %f", name, floatValue);
        } else if (strncmp(type, "@", 1) == 0) {
            id value = object_getIvar(self, ivar);
            NSLog(@"%s = %@", name, value);
        }
        // And the rest for other type encodings
    }
    free(ivars);
}

虽然我不特别建议在实践中这样做,但如果它是出于调试目的那么那就没关系。您可以在NSObject上将其实现为一个类别,并在调试时保持它可以使用。如果完成所有类型编码,那么它可以成为一个非常好的小方法。

答案 2 :(得分:2)

NSObject上现在有这些方法:

@interface NSObject (Private)
-(id)_ivarDescription;
-(id)_shortMethodDescription;
-(id)_methodDescription;
@end

迅速:

myObject.perform("_ivarDescription")

感谢this article

答案 3 :(得分:0)

是的,一种方法是询问所有属性,然后使用KVC例如:

//properties
unsigned int cProperties = 0;
objc_property_t *props = class_copyPropertyList(self.class, &cProperties);
for(int i = 0; i < cProperties; i++) {
    const char *name = property_getName(props[i]);
    NSLog(@"%@=%@", name, [self valueForKey:name];
}

另一种方法是遍历类的所有方法,获取返回类型,调用并打印它

答案 4 :(得分:-2)

快速而肮脏的是覆盖debugDescription

-(NSString*)debugDescription {
    NSString *str = [[NSString alloc] initWithFormat:@"My BOOL 1: %d, My Float: %f", self.myBool, self.myFoat];
    return str;
}

当然,如果您的对象很复杂,这可能会非常耗时。