iOS performSelector方法总结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS performSelector方法总结相关的知识,希望对你有一定的参考价值。
参考技术A底层实现 源码地址
performSelector是运行时系统负责去找方法,在编译时不会对调用的方法做检查,只有在运行的时候才会检查,如果方法存在就调用,如果放不存在就不会调用。当然也可以通过使用 - (BOOL)respondsToSelector:(SEL)aSelector;方法去判断对象是否实现了要调用的方法。
这三个方法调用都是直接执行,相当于直接通过对象调用方法, [self performSelector:@selector(test)];与[self test]; 执行的结果是一致的, 通过这些方法去执行是不需要子线程去启动Runloop的 。方法内运行的线程就是调用performSelector所在的线程
上面的方法,最多可以支持传递2个参数,如果要传递2个以上,上面的方法就不能使用了。
在苹果文档中的介绍:
这个方法是设置了一个timer,在当前线程的runloop上执行aSelector消息,这个计时器的默认模式是NSDefaultRunLoopMode。当计时器触发时,会尝试从runloop中取出消息行,如果runloop运行的模式是NSDefaultRunLoopMode,那么就会执行它,如果当前runloop是其他模式,则会等待runloop处于NSDefaultRunLoopMode在运行。
如果希望在运行循环处于NSDefaultRunLoopMode以外的其他模式时使消息出队,请改用performSelector:withObject:afterDelay:inModes:方法。如果不确定当前线程是否为主线程,则可以使用performSelectorOnMainThread:withObject:waitUntilDone:或performSelectorOnMainThread:withObject:waitUntilDone:modes:方法来确保选择器在主线程上执行。要取消排队的消息,请使用cancelPreviousPerformRequestsWithTarget:或cancelPreviousPerformRequestsWithTarget:selector:object:方法。
特别注意事项
此方法向其当前上下文的runloop进行注册,并依赖于runloop才能正确执行。一种常见情况是,当在 dispatch queue上调用这个方法,但是runloop并没有启动,这个方法是不会运行的。如果想使用这个延迟功能在dispatch queue上,则应使用dispatch_after和相关方法来获得所需的行为。
Runloop源码地址
iOS 私有 API performSelector 崩溃
【中文标题】iOS 私有 API performSelector 崩溃【英文标题】:iOS Private API performSelector crash 【发布时间】:2013-08-17 05:18:41 【问题描述】:基本上,我想获取 UIButton 的操作目标列表。我经历了this,我的问题略有不同,因为我不知道目标是什么。我只有一个 UIButton 对象。所以这就是我为捕获所有行动目标所做的工作。
受以下方法的启发,该方法在我将 firstResponder 对象作为有效指针的情况下工作。
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
UIView *firstResponder = [keyWindow performSelector:@selector(firstResponder)];
我在 UIKit 上使用 class-dump 查看 UIWindow 类,发现 firstResponder 如下。
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIWindow : UIView
@package
UIResponder *_firstResponder;
然后我通过类转储检查了 UIControl
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIControl : UIView
@package
NSMutableArray* _targetActions;
这就是我尝试做的事情,但它崩溃了。
NSMutableArray *arr = (NSMutableArray*)[((UIControl*)btn) performSelector:@selector(targetActions)];
NSLog(@"%@",arr);
听起来像是对我的阴谋。但更有可能是我在搞砸一些事情。有谁知道如何访问 UIControl 的 targetActions 数组?
编辑:这是错误消息 -
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '- [UIRoundedRectButton targetActions]: unrecognized selector sent to instance 0x1c0ab0'
任何帮助表示赞赏。
【问题讨论】:
你没有说崩溃的错误信息是什么。大概是选择器不存在吧? @Ross - 这是错误 - *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[UIRoundedRectButton targetActions]:无法识别的选择器已发送到实例 0x1c0ab0” 【参考方案1】:根据the UIControl documentation,发送以获取目标列表的消息是allTargets,而不是您建议的targetActions。解决方案的其余部分在接受How to get UIButton Target, Action and Control events?的答案中
当您不知道自己在做什么时可以使用的一种调试技术是使用 respondsToSelector 来检查您是否正在发送对象可以响应的消息: when to use respondsToSelector in objective-c
【讨论】:
我不需要实际调用 SEL,但我想记录选择器的名称。例如:如果该按钮绑定到一个函数“OnTouchMyButton”,当 TouchUpInside 事件发生时,我只需要我想要记录在文件中的那个函数的名称。 让我试试 allTargets 并返回。谢谢。 @Bugivor 首先获取目标,然后使用 actionsForTarget:forControlEvent: 我建议使用每个目标的选择器名称目的。您需要阅读文档。 它有效/+1 并接受了答案。我还有2个疑问?如果您知道,请欣赏 - 1) 为什么我不能像获得 firstResponder 那样获得 targetActions? 2) forControlEvents - 文档说一次只允许 1 个常量。如何传递一个通用值,以便获得所有控制事件的操作? @Bugivore 大概 firstResponder 是一个有效的(但私有的)选择器,这就是它起作用的原因。如您所见,没有 allTargets 选择器。另见:***.com/questions/1823317/…以上是关于iOS performSelector方法总结的主要内容,如果未能解决你的问题,请参考以下文章
iOS - 如何实现具有多个参数和 afterDelay 的 performSelector?
ios performSelector:withObject:afterDelay: in viewDidLoad 冻结视图推送