13

iOS 万能跳转界面方法

 3 years ago
source link: https://zhuanlan.zhihu.com/p/116635292
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

iOS 万能跳转界面方法

只是一个小透明。

作者:饶旭东

在使用 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;
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK