1.iOS系统本身没有提供获取一个类所有属性的功能,如果你跟我一样经常使用字典来对象赋值,就会碰到烦人的“this class is not key value coding-compliant for the key xxx”;如果可以提前判断这个对象是否有这个属性,就可以避免这个崩溃了。
-(NSArray *)property_names{
unsigned int outCount;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
NSMutableArray* props = [NSMutableArray array];
for (int i = 0; i< outCount; i++) {
objc_property_t property = properties[i];
const char* char_f =property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:char_f];
[props addObject:propertyName];
}
free(properties);
return props;
}
给NSObject添加一个category,然后加上这个方法,就可以获取任意对象的属性列表了。
2.有时候,不仅想得到所有的属性名,我还想得到对应的属性值,也就是把一个对象转成字典来表示,怎么办?只要在上面的基础上做稍许的改动
/* 获取对象的所有属性 */
- (NSDictionary *)properties_aps
{
NSMutableDictionary *props = [NSMutableDictionary dictionary];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for (i = 0; i<outCount; i++)
{
objc_property_t property = properties[i];
const char* char_f =property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:char_f];
//把对应的值也取出来
id propertyValue = [self valueForKey:(NSString *)propertyName];
if (propertyValue) [props setObject:propertyValue forKey:propertyName];
}
free(properties);
return props;
}
可能很多人没有这种需求,我是因为:要经常的使用类似的控件在许多不同的项目里-->所以把这些控件抽象出来,通过一些参数来调控-->当参数多了就把参数用json的格式组织起来,因为可能有好多层,比如A界面是一个tableView、每个cell进去是一个collectionView,然后collectionView的cell点击进去还有东西,而这些一连串的界面可能都是通用的控件,那从一开始传递的参数就需要是多层的了-->所以就需要json、NSDictionary、对象的相互转化。
有了上面的方法,对象可以转成字典,而通过
//使用字符串构建对象
Class class = NSClassFromString("classname");
id target = [[class alloc]init];
//使用字典给对象赋值
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;
来赋值对象;
字典和json转就简单了,系统有提供方法。打通了对象到字符串的通道,而字符串可以通过网络接口获得,那么可以像web一样,从后台获取配置信息(字符串),然后转成对象,本地界面、操作根据这些来变化。就可以达到极大的便利。
一点思考:
一开始的目的只是“把通用的控件抽象出来”,后来越写越感觉像web,参数多了->写成json格式文件,这TM不就是脚本吗?如果我实现了巨多的控件类型,并且也发明了一套完整的规则来:告诉你怎么写会得到什么样的界面以及这些界面怎么交互。这不就是浏览器吗?
只是我现在做的项目只是某个很小范围的,也没能力去做完整的解决方案,只是这种思路是ok的,想要包罗万象,那配置文件也会变得相当复杂,但是如果是自己特定领域的项目,可以做一套简单、但更具适应性的解决方案:达到使用配置文件(json\xml或其他脚本文件甚至自己定义解析方式的文件)通过网络来控制界面,甚至可以每个用户登录后,根据他的属性配置一套定制的界面。
这会不会比使用�已有的web+native的解决方案更好呢,毕竟这样还更契合自己的项目。
其实APP界面就那么些,随着时间推移,每一种都会出现足够完美的样式,在我要求不高的时候,是不是可以拿来用就是,不用写swift或OC代码,用脚本把这些控件串起来就行了。