swizling - method_exchangeImplementations

        每天进步一点点,由浅入深,不急不躁。。又到了快乐的coding时间,下面开始介绍的是,大家熟知的swizling,也通常被称之为hook。

        平常大家用这家伙是什么场景下呢?我最初接触这个东西还是之前的一个面试官给的一道面试题:

        Q:在AppStore上如何捕获用户点击下载按钮的事件,并且改变这个事件的指向呢?

        

        初出接到这个问题我是蒙B的,这是个什么问题?你在AppStore 的点击事件我TM怎么接受的到,你逗我呢?然后忽然醒悟。。这家伙不会在考我底层吧。。。《这东西是什么?这东西怎么用?这东西为什么要去用?》

        是的,这个问题的解决方法可以使用swizling很方便的实现,当然这里我不写实现方法哈,我这里不知道AppStore内部点击方法的名称是什么。。很尴尬。。。

        这边我想说的是这个思路,取出AppStore内部点击方法的名称,暂且称之为ApsMethod吧,自己声明一个方法,称之为changeTestMethod吧,然后调用交换方法即可实现:下面是伪代码:

            MethodApsMethod = class_getClassMethod(AppStoreClass,@selector(btnClick:));

            MethodchangeTestMethod =class_getClassMethod(self,@selector(zh_BtnClick:));

            method_exchangeImplementations(ApsMethod, changeTestMethod);


            Swizzling应该总是在+load中执行。。。。Why????

            在Objective-C中,运行时会自动调用每个类的两个方法。+load会在类初始加载时调用,+initialize会在第一次调用类的类方法或实例方法之前被调用。这两个方法是可选的,且只有在实现了它们时才会被调用。由于method swizzling会影响到类的全局状态,因此要尽量避免在并发处理中出现竞争的情况。+load能保证在类的初始化过程中被加载,并保证这种改变应用级别的行为的一致性。相比之下,+initialize在其执行时不提供这种保证–事实上,如果在应用中没为给这个类发送消息,则它可能永远不会被调用。

                Swizzling 应该总是在dispatch_once中执行

            与上面相同,因为swizzling会改变全局状态,所以我们需要在运行时采取一些预防措施。原子性就是这样一种措施,它确保代码只被执行一次,不管有多少个线程。GCD的dispatch_once可以确保这种行为,我们应该将其作为method swizzling的最佳实践。


            好了,这里就实现了方法的交换,如果面试问到你这个问题,你直接这么回答,面试官会大喊一句:nice   ~

            这里做一个问题延伸,既然可以拿到每一个类里面的方法,我可以不导入头文件获取到每一个我知道类名里面的方法么?

            这个放在下一个来讲吧~~~

你可能感兴趣的:(swizling - method_exchangeImplementations)