有时候面对推送会有很多的的类型,要跳到不同界面,看了cocoaChina之后使用runtime进行这样的逻辑操作会好很多。
首先说一下适用的环境:
具体就是先跟服务器那边说好推送规则,里面有要跳的类的类名,和相关的属性及其值,然后在接到推送的时候使用runtime的动态创建对象进行跳转,由于使用了runtime之后对类来说属性就不分基本数据类型或者非基本数据类,可以不进行解包和封包操作。
具体代码如下,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| - (void)push:(NSDictionary *)params { NSString *class =[NSString stringWithFormat:@"%@", params[@"class"]]; const char *className = [class cStringUsingEncoding:NSASCIIStringEncoding]; Class newClass = objc_getClass(className); if (!newClass) { Class superClass = [NSObject class]; newClass = objc_allocateClassPair(superClass, className, 0); objc_registerClassPair(newClass); } id instance = [[newClass alloc] init]; NSDictionary * propertys = params[@"property"]; [propertys enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { if ([self checkIsExistPropertyWithInstance:instance verifyPropertyName:key]) { [instance setValue:obj forKey:key]; } }]; UIWindow * keyWindow = [UIApplication sharedApplication].keyWindow; UINavigationController * pushClassStance = (UINavigationController *)keyWindow.rootViewController; [pushClassStance pushViewController:instance animated:YES]; }
- (BOOL)checkIsExistPropertyWithInstance:(id)instance verifyPropertyName:(NSString *)verifyPropertyName { unsigned int outCount, i; objc_property_t * properties = class_copyPropertyList([instance class], &outCount); for (i = 0; i < outCount; i++) { objc_property_t property =properties[i]; NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding]; if ([propertyName isEqualToString:verifyPropertyName]) { free(properties); return YES; } } free(properties); return NO; }
|
那么举个例子,这里的推送规则是这样的:
1 2 3 4
| NSDictionary *userInfo = @{@"class": @"HLLTableViewController", @"property": @{@"titleName": @"HLL"}};
[self push:userInfo];
|
其实这样的做法还有一个弊端,和KVC一样,服务器推送过来的类名要够正确没有错别字。