performSelector:withObject:afterDelay:无法调用handler方法问题求助
兄弟,先看你代码里最扎眼的一个问题:initWithType:的参数是NSInteger *Handler(指针类型),但你在switch里直接用Handler——这其实是在判断指针的内存地址值,而不是你传入的整数标识啊!
正常来说,如果你的参数是用来传整数类型的handler类型,要么把参数改成非指针的NSInteger Handler,要么在switch里解引用指针:switch(*Handler)。这个错误会直接导致你的case分支根本不会正确匹配,sync方法里传入的selector大概率不是你预期的handler1:或handler2:,这绝对是第一个要排查的点!
假设selector已经传对了,那performSelector:withObject:afterDelay:0不执行还有这几个常见原因:
后台线程Runloop未启动:如果
sync是在后台线程执行的,后台线程默认没有启动runloop,而afterDelay:的任务依赖当前线程的runloop调度——哪怕延迟设为0,它也会被放到runloop的下一个循环执行。如果runloop没启动或者线程执行完sync就退出了,这个任务就永远没机会运行。你可以试试换成[self performSelectorOnMainThread:handler withObject:data waitUntilDone:NO](如果handler可以在主线程执行),或者在后台线程手动启动runloop。方法签名不匹配:检查
handler1:和handler2:的方法定义,必须是-(void)handler1:(id)data;这种格式——返回值为void,且接受一个id类型的参数。如果方法参数是NSData*这类具体类型,或者返回值不是void,performSelector可能会静默失败(Debug模式下可能会触发警告)。self提前被释放:如果调用
performSelector后,self很快被释放(比如这个实例是局部变量,没有被强引用持有),那么消息发送给已释放的对象,自然不会执行方法,甚至可能导致崩溃。你可以在dealloc方法中添加日志,确认self是否在performSelector执行前就被销毁了。
最后给你个快速验证的小技巧:在sync方法里添加一句日志:
NSLog(@"即将调用的selector: %@", NSStringFromSelector(handler));
通过日志确认传入的selector确实是handler1:或handler2:,这能快速验证第一个问题是否存在。
内容的提问来源于stack exchange,提问作者Vineal Viji

