引言
大家或多或少都使用过音乐播放器App,播放器的底部工具条一般都是展示着当前播放的歌曲信息,以及拥有控制当前歌曲播放和暂停功能。无论我们在哪个界面点击了歌曲播放,底部工具条都会更新相应的信息,那么这要怎么实现呢?笔者思考之后,觉得设置通知
是一个可行之法:当我们点击某个控件(比如tableViewCell)时,就在其响应方法中(tableView:didSelectRowAtIndexPath:)发布一个自定义名称的通知,该通知将点击播放的歌曲信息传递给监听者,然后设置底部工具条监听该通知,工具条就可以通过传递的参数来更新自己的显示。
- 问题:通知传递的参数是
(NSDictionary *)
类型的,我们如何传递歌曲信息?(一般我们会将歌曲封装成模型,将歌曲信息作为歌曲的属性)。笔者试验过将对象直接转成字典来传递,结果遇到了难点无法解决,况且直接传递模型还存在一个缺陷,那就是监听该通知的文件都必须包含(#import)该模型对象。于是笔者又有了新的思考。 - 解决方法:自定义分类方法,将模型属性抽取出来,分别转换成字典的键值对(属性 - 属性值 )
以下为笔者搜索整理得到的分类,并做了详细说明:
主要思路:
通过定义在<objc/runtime.h>中的class_copyPropertyList方法获取属性数组的首元素地址,通过数组首元素地址遍历得到所有属性
。其次,属性值
的获取是通过KVC中的valueForKey
方法,该方法同时可以将非对象类型(如BOOL, int等)转换成NSNumber。如果属性是数组、字典和对象类型,还有对属性值进行嵌套处理,最终将所有属性值转化成基本Objective-C类型。
+ (NSDictionary*)dictionaryWithObject:(id)obj
{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
//定义存储属性数量的变量
unsigned int propersCount;
//指向属性数组的指针,可以访问数组中的所有属性,传入存储属性数量的变量的地址,该方法就会为其赋值
objc_property_t *propers = class_copyPropertyList([obj class], &propersCount);
//遍历属性
for(int i = 0;i < propersCount; i++) {
objc_property_t proper = propers[i];
//获得字符串类型的属性名
NSString *properName = [NSString stringWithUTF8String:property_getName(proper)];
//通过KVC取得属性值
id value = [obj valueForKey:properName];
if(value == nil) {
value = [NSNull null];
} else { //如果属性值不为空,则判断属性值类型
value = [self objectByPropertyValue:value];
}
[dict setObject:value forKey:properName];
}
return dict;
}
属性的嵌套处理
+ (id)objectByPropertyValue:(id)obj {
//对NSString、NSNumber、NSNull类型的属性值不做处理,直接返回
if([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:[NSNull class]]) {
return obj;
//如果是数组类型,则遍历数组查看数组内部是否存在对象类型
} else if([obj isKindOfClass:[NSArray class]]) {
NSArray *objArray = obj;
NSMutableArray *array = [NSMutableArray arrayWithCapacity:objArray.count];
for(int i = 0;i < objArray.count; i++) {
//嵌套
[array setObject:[self objectByPropertyValue:[objArray objectAtIndex:i]] atIndexedSubscript:i];
}
//返回转化后的数组
return array;
//字典类型
} else if([obj isKindOfClass:[NSDictionary class]]) {
NSDictionary *objDict = obj;
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:[objDict count]];
for(NSString *key in objDict.allKeys) {
[dict setObject:[self objectByPropertyValue:[objDict objectForKey:key]] forKey:key];
}
//返回转化后的字典
return dict;
}
//对象类型等
return [self objectByPropertyValue:obj];
}
网友评论