iOS Runtime实用---万能控制器跳转

iOS开发过程中,我们会遇到控制器跳转的问题。
几种情况:

  • 1.推送:根据服务器推送过来的信息,跳转不同控制器;
  • 2.首页轮播图:首页轮播图一般展示的信息都是各模块的精彩信息,跳转控制器一般都会有几种;
  • 3.还有一些奇葩的需求吧(哈哈),比如一个列表cell跳转不同控制器;

这些需求,我们可以在移动端使用if else或者switch判断不同类型,实现跳转,但是想一想,是不是特别麻烦,肯定都有拿板砖的冲动了!
思考一下:是不是可以通过下面的方法解决呢,方便灵活!请看代码:

  • WMJumpControllerTool.h

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface WMJumpControllerTool : NSObject
    
    /**
    控制器跳转的方法
    params:跳转所需要的信息,这个需要和服务器端沟通好,包含信息:需要跳转的控制器名,跳转需要的字段以及其他可能的信息。
    */
    + (void)jumpViewControllerWithParams:(NSDictionary *)params;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
  • WMJumpControllerTool.m

    #import "WMJumpControllerTool.h"
    #import <UIKit/UIKit.h>
    #import <objc/runtime.h>
    
    @implementation WMJumpControllerTool
    
    /**
    params此处的格式为:
    @{
      @"class":@"跳转目标类名",
      @"property":@{
      				@"name":@"字段"
                   	},
     };
     此为服务器返回数据,包含目标控制器字段:目标控制器名,属性名和属性值
     我们需在目标控制器.h文件中声明对应的属性名的属性。
    */
    + (void)jumpViewControllerWithParams:(NSDictionary *)params {
    	///获取控制器类名字符串
    	NSString *classNameStr = [NSString stringWithFormat:@"%@", params[@"class"]];
    	const char *className = [classNameStr 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 ([WMJumpControllerTool checkIsExistPropertyWithInstance:instance verifyPropertyName:key]) {
            	// 利用 KVC 对控制器对象的属性赋值
            	[instance setValue:obj forKey:key];
        	}
    	}];
    
    	// 跳转到对应的控制器
    	[[WMJumpControllerTool topViewController].navigationController pushViewController:instance animated:YES];
    }
    
    // 检测对象是否存在该属性
    + (BOOL)checkIsExistPropertyWithInstance:(id)instance verifyPropertyName:(NSString *)verifyPropertyName {
    	unsigned int count, i;
    	// 获取对象里的属性列表
    	objc_property_t *properties = class_copyPropertyList([instance class], &count);
    	for (i = 0; i < count; 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;
    }
    
    // 获取当前显示在屏幕最顶层的 ViewController
    + (UIViewController *)topViewController {
    	UIViewController *resultVC = [WMJumpControllerTool _topViewController:[[UIApplication sharedApplication].keyWindow rootViewController]];
    	while (resultVC.presentedViewController) {
        	resultVC = [WMJumpControllerTool _topViewController:resultVC.presentedViewController];
    	}
    	return resultVC;
    }
    
    + (UIViewController *)_topViewController:(UIViewController *)vc {
    	if ([vc isKindOfClass:[UINavigationController class]]) {
        	return [WMJumpControllerTool _topViewController:[(UINavigationController *)vc topViewController]];
    	} else if ([vc isKindOfClass:[UITabBarController class]]) {
        	return [WMJumpControllerTool _topViewController:[(UITabBarController *)vc selectedViewController]];
    	} else {
        	return vc;
    	}
    	return nil;
    }
    @end
    

举例:

NSDictionary *dict = @{
						@"class":@"WMJumpController",
						@"property":@{
										@"name":@"Hello World!"
										},
									};
[WMJumpControllerTool jumpViewControllerWithParams:dict];

好啦,实现了!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值