我正在做一些电话调用背景处理的实验,并发现我无法获得performSelector:withObject:afterDelay如果从块内间接调用则调用fire,但如果直接调用则会触发
此代码显示我的意思:
@implementation MyAppDelegate
- (void) sausages
{
NSLog(@"*************Sausages");
[self performSelector:@selector(sausages) withObject:nil afterDelay:10];
}
- (void) sausages2
{
NSLog(@"*************Sausages 2");
[self performSelector:@selector(sausages2) withObject:nil afterDelay:10];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
[self sausages2];
MyAppDelegate __weak *weakSelf = self;
[self.callCenter setCallEventHandler:^(CTCall *call)
{
if ([call.callState isEqualToString: CTCallStateIncoming])
{
NSLog(@"Incomming");
[weakSelf sausages];
}
}];
当我运行此代码并将应用程序切换到后台时,banages2方法每10秒触发一次(应用程序的位置背景模式未显示在代码段中)。
当我打电话给设备然后接听电话然后在通话期间,香肠2方法仍然每10秒触发一次,但香肠方法只触发一次。这是为什么?为什么在电话会议期间不断调用香肠方法,但香肠方法是什么?
答案 0 :(得分:3)
问题是setCallEventHandler
无疑是异步运行的,并且你不能使用performSelector
延迟来自除主队列之外的任何东西上运行的异步块(因为它需要{{1} }})。
它更容易使用NSRunLoop
,它不会受此问题的影响。例如,如果要在十秒钟后在主队列上调用dispatch_after
,则可以执行以下操作:
someMethod
或者,如果您希望它在某个后台队列上运行:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self someMethod];
});
话虽如此,看起来你想要反复调用这个方法,所以我可能只是倾向于使用dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self someMethod];
});
或调度源定时器,而不是让方法在10秒后自行调用。例如,如果从主队列启动此计时器,则您需要定义属性:
NSTimer
然后如果从主队列开始,那就简单如下:
@property (nonatomic, strong) NSTimer *timer;
如果从完成块启动此计时器,您可能必须在主runloop上明确安排计时器:
self.timer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(someMethod:) userInfo:nil repeats:YES];
self.timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(someMethod:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
将被定义为将someMethod
作为参数:
NSTimer
顺便说一下,在做重复计时器时,记得- (void)someMethod:(NSTimer *)timer
{
NSLog(@"%s: %@", __PRETTY_FUNCTION__, timer);
}
计时器,例如视图消失,以避免强烈的参考周期:
invalidate