在使用 JPush 、JMessage、JMLink 等 SDK 时,iOS 客户端可能会收到下发的通知,或者收到回调里的返回参数,在拿到参数后可能会有些场景需要跳转到目标页。
通过 runtime 机制我们可以灵活的在服务端控制某条消息跳转到对应目标页。
runtime是个好东西
利用 runtime 动态生成对象、属性和方法的特性,我们可以先跟服务端商量好,定义跳转规则。比如要跳转到 A 控制器,需要传属性 id、type,那么服务端返回字典给我后,会有控制器名、两个属性名跟属性值,客户端可以根据控制器名生成对象,再用 kvc 给对象赋值,这样就搞定了。
比如:根据推送规则跳转对应界面 HSFeedsViewController
HSFeedsViewController.h:
进入该界面需要传的属性
objc
@interface HSFeedsViewController : UIViewController
// 注:根据下面的两个属性,可以从服务器获取对应的频道列表数据
/** 频道ID */
@property (nonatomic, copy) NSString *ID;
/** 频道type */
@property (nonatomic, copy) NSString *type;
AppDelegate.m:
推送过来的消息规则
objc
// 这个规则肯定事先跟服务端沟通好,跳转对应的界面需要对应的参数
NSDictionary *userInfo = @{
@"class": @"HSFeedsViewController",
@"property": @{
@"ID": @"123",
@"type": @"12"
}
};
接收推送消息
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
[self push:userInfo];
}
魔链回调拿到参数
[JMLinkService registerMLinkDefaultHandler:^(NSURL * _Nonnull url, NSDictionary * _Nullable params) {
[self push:userInfo];
}];
跳转界面
- (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]) {
// 利用kvc赋值
[instance setValue:obj forKey:key];
}
}];
// 获取导航控制器
UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController;
UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex];
// 跳转到对应的控制器
[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;
}
关于极光
极光(Aurora Mobile,纳斯达克股票代码:JG)成立于2011年,是中国领先的开发者服务提供商。极光专注于为移动应用开发者提供稳定高效的消息推送、即时通讯、统计分析、极光分享、短信、一键认证、深度链接等开发者服务。截止到2019年12月份,极光已经为超过50万移动开发者和145.2万款移动应用提供服务,其开发工具包(SDK)安装量累计336亿,月度独立活跃设备13.6亿部。同时,极光持续赋能开发者和传统行业客户,推出精准营销、金融风控、市场洞察、商业地理服务产品,致力于为社会和各行各业提高运营效率,优化决策制定。