Skip to content

Instantly share code, notes, and snippets.

@zekunyan
Last active August 29, 2015 14:26
Show Gist options
  • Save zekunyan/1944ab1101afd5c978b5 to your computer and use it in GitHub Desktop.
Save zekunyan/1944ab1101afd5c978b5 to your computer and use it in GitHub Desktop.
Runtime check object property example.
//
// main.m
// OC-Test1
//
// Created by zorro on 14-7-23.
// Copyright (c) 2014年 zorro. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
/**
* 解析Property的Attributed字符串,参考Stackoverflow
*/
static const char *getPropertyType(objc_property_t property) {
const char *attributes = property_getAttributes(property);
NSLog(@"%s", attributes);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
// 非对象类型
if (attribute[0] == 'T' && attribute[1] != '@') {
// 利用NSData复制一份字符串
return (const char *) [[NSData dataWithBytes:(attribute + 1) length:strlen(attribute) - 1] bytes];
// 纯id类型
} else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
return "id";
// 对象类型
} else if (attribute[0] == 'T' && attribute[1] == '@') {
return (const char *) [[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
}
}
return "";
}
/**
* 给对象的属性设置默认值
*/
void checkEntity(NSObject *object) {
// 不同类型的字符串表示,目前只是简单检查字符串、数字、数组
static const char *CLASS_NAME_NSSTRING;
static const char *CLASS_NAME_NSNUMBER;
static const char *CLASS_NAME_NSARRAY;
// 初始化类型常量
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// "NSString"
CLASS_NAME_NSSTRING = NSStringFromClass([NSString class]).UTF8String;
// "NSNumber
CLASS_NAME_NSNUMBER = NSStringFromClass([NSNumber class]).UTF8String;
// "NSArray"
CLASS_NAME_NSARRAY = NSStringFromClass([NSArray class]).UTF8String;
});
@try {
unsigned int outCount, i;
// 包含所有Property的数组
objc_property_t *properties = class_copyPropertyList([object class], &outCount);
// 遍历每个Property
for (i = 0; i < outCount; i++) {
// 取出对应Property
objc_property_t property = properties[i];
// 获取Property对应的变量名
NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
// 获取Property的类型名
const char *propertyTypeName = getPropertyType(property);
// 获取Property的值
id propertyValue = [object valueForKey:propertyName];
// 值为空,才设置默认值
if (!propertyValue) {
// NSString
if (strncmp(CLASS_NAME_NSSTRING, propertyTypeName, strlen(CLASS_NAME_NSSTRING)) == 0) {
[object setValue:@"" forKey:propertyName];
}
// NSNumber
if (strncmp(CLASS_NAME_NSNUMBER, propertyTypeName, strlen(CLASS_NAME_NSNUMBER)) == 0) {
[object setValue:@0 forKey:propertyName];
}
// NSArray
if (strncmp(CLASS_NAME_NSARRAY, propertyTypeName, strlen(CLASS_NAME_NSARRAY)) == 0) {
[object setValue:@[] forKey:propertyName];
}
}
}
// 别忘了释放数组
free(properties);
} @catch (NSException *exception) {
NSLog(@"Check Entity Exception: %@", [exception description]);
}
}
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@end
@implementation Person
@end
int main(int argc, const char *argv[]) {
@autoreleasepool {
Person *person = [Person new];
checkEntity(person);
NSLog(@"name: %@", person.name);
}
return 0;
}
/*
输出:
2015-08-08 00:05:48.732 Common[35087:1077311] T@"NSString",C,N,V_name
2015-08-08 00:05:48.733 Common[35087:1077311] name:
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment