2014-04-30 34 views
2

我在通話過程中進行了一些後臺處理實驗,發現我無法獲得performSelector:withObject:afterDelay調用來觸發if它是從一個塊內部間接調用的,但是如果直接調用它將會觸發。performSelector:withObject:afterDelay當通過塊間接調用時不會被調用,但在其他情況下不會調用

這段代碼顯示了我的意思是:

@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]; 
      } 
     }]; 

當我運行這段代碼和應用程​​序切換到後臺,則sausages2方法獲取每10秒觸發(應用程序在沒有顯示的位置後臺模式代碼片段)。

當我打電話給設備並接聽電話時,在通話過程中,sausages2方法每10秒鐘仍會繼續觸發,但是香腸方法只觸發一次。這是爲什麼?爲什麼香腸方法在調用過程中不斷被調用,但是香腸2方法是?

+0

可能你需要你的香腸功能在主隊列上執行選擇器?只是一個猜測。 – Augie

回答

3

的問題是,setCallEventHandler無疑是異步運行,並且不能有延遲使用performSelector來自於什麼,但主隊列中運行,(因爲它需要一個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]; 
}); 

說了這麼多,看起來你想重複調用這個方法,所以我可能只是傾向於使用NSTimer或調度源定時器,而不是讓方法在10秒後調用它自己。例如,如果開始從主隊列這個定時器,你會定義一個屬性:

@property (nonatomic, strong) NSTimer *timer; 

然後,如果從主隊列開始本,這將是簡單:

self.timer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(someMethod:) userInfo:nil repeats:YES]; 

如果開始從你的完成阻止此計時器,你可能有明確安排在主runloop定時器:

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計時器時,例如,在視圖中消失,避免了強烈的基準週期:

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [super viewDidDisappear:animated]; 

    [self.timer invalidate]; 
} 
+0

謝謝,我會嘗試。 – Gruntcakes