• iOS(Swift)-Runtime之关于页面跳转的捷径【Runtime获取当前ViewController,很常用】


    写在前面

    在我们操作页面跳转时,如果当前的类不是UIViewcontroller(下面用VC表示),你会不会写一个代理,或者block给VC传递信息,然后在VC里面进行

     ///假如targetVc是将要跳转的页面
     [self.navigationController pushViewController:targetVc animated:YES];

    拿tableViewCell做例子,如果每个页面展示的tableViewCell中,如果存在不少的这样操作,就会写很多代理或者block,如果不这样,那又该怎么做呢,思路是获取当前显示在最顶层的VC,网上有很多方法,先看一个普通的方法

    - (UIViewController *)currentViewController {
        UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
        UIViewController *vc = keyWindow.rootViewController;
        while (vc.presentedViewController) {
            vc = vc.presentedViewController;
            
            if ([vc isKindOfClass:[UINavigationController class]]) {
                vc = [(UINavigationController *)vc visibleViewController];
            } else if ([vc isKindOfClass:[UITabBarController class]]) {
                vc = [(UITabBarController *)vc selectedViewController];
            }
        }
        return vc;
    }

    上面的方法可以或许可以获取最顶层的VC(我在网上找的一个,没有测试,这里只做对比),但是有没有感觉很繁琐,当然也可以把它写在一个工具里面,每次用这个工具里面的这个方法,也可以获取,但是我始终觉得繁琐,哈哈;

    利用Runtime实现

    runtime是一个好玩的东西,上一篇我简单说了它的一些常用功能,这里结合Category来实现获取当前VC需求

    1.新建一个基于UIApplication的分类

    点击下一步就建好了

    2.利用Runtime添加属性

    在UIApplication+CurrentViewController.h文件中,添加

    ///用于获取当前 UIViewController
    @property (nonatomic, weak) UIViewController *currentViewController;

    在UIApplication+CurrentViewController.m文件中,引入头文件

    #import <objc/runtime.h>

    利用runtime实现属性的get set方法

    ///set
    - (void)setCurrentViewController:(UIViewController *)currentViewController{
        objc_setAssociatedObject(self, @selector(currentViewController), currentViewController, OBJC_ASSOCIATION_ASSIGN);
    }
    ///get
    - (UIViewController *)currentViewController{
        return objc_getAssociatedObject(self, _cmd);
    }

    3.实现

    在需要获取当前VC的文件中,引入头文件,也可以直接将该头文件放入宏文件中

    #import "UIApplication+CurrentViewController.h"

    在VC的viewWillAppear方法中,添加

    [UIApplication sharedApplication].currentViewController = self;

    这样,我们在任何一个地方获取,只需要添加如下代码,就可以获取当前的VC,获取到之后,不管是push、present还是performSegueWithIdentifier,都可以实现页面的跳转

    UIViewController *viewVc = [UIApplication sharedApplication].currentViewController;

    4.延伸

    上面在需要用到的在每一个VC中都需要添加

    [UIApplication sharedApplication].currentViewController = self;

    那么,可以建一个基于UIViewController的基类BaseViewController,然后在BaseViewController的viewWillAppear方法中添加上述代码,我们在新建VC时,只需要继承BaseViewController就可以了!

    *****************Swift实现*****************

    extension UIApplication {
        struct RuntimecurrVcKey {
            static let currVcKey = UnsafeRawPointer.init(bitPattern: "currVcKey".hashValue)
        }
    
        var currViewController: UIViewController? {
            get {
                return  objc_getAssociatedObject(self, UIApplication.RuntimecurrVcKey.currVcKey!) as? UIViewController
            }
            set(newValue) {
                objc_setAssociatedObject(self, UIApplication.RuntimecurrVcKey.currVcKey!, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
            }
        }
    }
  • 相关阅读:
    JMeter:全面的乱码解决方案
    代码静态扫描工具sonar
    jmeter接口测试
    MVC模式
    Android--HttpClient
    android SQLite使用SQLiteOpenHelper类对数据库进行操作
    反射
    列约束
    MVC的处理过程
    android项目中values中几个文件的作用
  • 原文地址:https://www.cnblogs.com/wangkejia/p/8320946.html
Copyright © 2020-2023  润新知