在项目中,我们可能碰到这样的情况,产品想要一个灵活的入口。比如首页的轮播banner、商品中间穿插的banner等等。这些入口可能跳转详情页,也可能是web页,也可能是分类页。那么怎么实现让后台服务器来控制客户端跳转呢?
首先跟后台约定好,增加两个字段:template、paramete。一个用来创建控制器,一个是创建好的控制器里请求的参数,然后给所有想支持动态跳转的控制器起好名字,例如详情页叫XXX_Detail。
当我们收到服务器传来的template和paramete时,我们根据template的值:XXX_Detail,去寻找与其对应的控制器名字XXX_DetailController。 (这里不推荐让后台直接传递控制器名字,因为随着工程越来越大,控制器越来越多,可能会觉得原来的控制器名字起得不好或新加的控制器更适合那个名字而发生更改)
- (id)viewControllerGenericFromScheme:(NSString *) className {
const char * classNameCString = [className cStringUsingEncoding:NSASCIIStringEncoding];
/* 使用字符串获取一个类 */
Class _controllerClass= objc_getClass(classNameCString);
if (_controllerClass==nil) {
Class superClass = [NSObject class];
_controllerClass = objc_allocateClassPair(superClass, classNameCString, 0);
objc_registerClassPair(_controllerClass);
}
/* 创建实例对象 */
id instance = [[_controllerClass alloc] init];
// ((UIViewController )instance).hidesBottomBarWhenPushed = YES;
// 属性自动赋值 /
[self autoSetInstanceProperty:instance];
return instance;
}
- (void)autoSetInstanceProperty:(id)instance{
NSString * _paramete = [self parametePropertyValue];
[instance setValue: _paramete forKey:@"paramete"];
/* 多个参数可以仿照此参数继续赋值 */
}
- (NSString *) parametePropertyValue {
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];
NSString * key = [[NSString alloc]initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
id propertyValue = [self valueForKey:key];
if ([key isEqualToString:@"paramete"]) {
if (![Common isBlankString:propertyValue]) {
return propertyValue;
} else {
return nil;
}
}
}
return nil;
}
//判断字符串是否为空
//判断字符串是否为空
+ (BOOL)isBlankString:(NSString *)string {
if (string == nil || string == NULL) {
return YES;
}
if ([string isKindOfClass:[NSNull class]]) {
return YES;
}
if ([[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length]==0) {
return YES;
}
return NO;
}
这样,只要在外面使用模型传入控制名字就可以返回一个控制器的实例对象。
UIViewController *createVc = [model viewControllerGenericFromScheme:className];
有了控制器实例对象,然后跳转过去就可以了,此方法也可用于收到推送后的处理,只要将template、paramete携带在推送里,就可以跳到指定页面,并用paramete进行请求。