面试时被问及的一个问题,容我技术菜接触少被问及时虽然吞吞吐吐说了点,但毕竟没接触也不是很有信心,具体怎么实现更不用说了。面试完回来后就翻阅各种文章发现用的最多的就是Runtime
的方法交换功能了。在此只是个人的知识点整理,各位客官如有不足多多提点。
首选创建一个UIButton的分类
1 | // .h中添加该属性 用于调用时设置延迟时间 这样不同的button可以设置不同的延迟时间 |
既然添加了属性当然就要利用Runtime
的添加属性功能为delay_interval设置对应的getter和setter方法。
1 | - (NSTimeInterval)delay_interval { |
在.m中一个BOOL用来判断按钮的点击状态
1 | @interface UIButton () |
设置getter和setter
1 | - (BOOL)clickBool { |
设置相关Key
1 | static char * const delayintervalkey = "delayintervalkey"; |
接下来就是方法交换的实现了
1 | + (void)load { |
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
方法的作用在于当交换方法完成且已被点击后重新设置按钮的状态以用来触发下一次点击。这个方法是单线程的,也就是说只有当前调用此方法的函数执行完毕后,selector方法才会被调用
最后就是调用了
1 | // 设置延迟时间即可 |
正常点击的时候发现并没有什么问题,然而当我PUSH后在点击返回按钮时竟然崩溃了。报错信息如下
1 | 2019-05-11 13:44:22.938692+0800 Test[1336:125411] -[_UIButtonBarButton clickBool]: unrecognized selector sent to instance 0x10084e6b0 |
问题应该是_UIButtonBarButton找不到调用的方法。我的理解是我们只是在UIButton
的分类下调换了父类UIControl
的- (void)sendAction:(SEL)action to:(nullable id)target forEvent:(nullable UIEvent *)event;
方法。而不是在父类下直接交换了方法,导致在其他类调用- (void)sendAction:(SEL)action to:(nullable id)target forEvent:(nullable UIEvent *)event;
方法时而找不到对应的方法从而崩溃。
- 所以交换方法的分类改成
UIControl
而不应该是UIButton
. 这样其他子类在调用时不会受影响。
- 总结后发现这么一个需求就利用到了
Runtime
的多个功能点。不得不说Runtime
在某些功能上的功能强大。也正好为最近的Runtime
学习整理来一个很好的例子。