1

[NOT重複:讀好這個問題,並已經給出答案,我已經閱讀]​​_async進行選擇警告VS調度

我面臨這個問題,我需要替換-performSelector方法,因爲它導致的是,在編譯器警告與ARC

performSelector可能會導致泄漏,因爲它的選擇是未知

我知道,有不同有關該主題的問題:

,我也意識到有關的技術,以避免該警告。
有時作爲解決方案,我發現建議最多的建議是使用dispatch_async(dispatch_get_main_queue(),^(void) { WHATEVER }); ,但據我所知,調度將需要在下一個運行循環中執行該塊,因此立即執行-performSelector(沒有延遲)。
爲什麼這種心理手淫?假設您正在使用新的Gamekit方法進行身份驗證,遊戲工具包可以將auth塊內的視圖控制器發送給您,以使用戶執行一些操作(例如創建ID,登錄等)。如果他/她想要看到該視圖控制器,可能會警告用戶。爲了做到這一點,我正在編寫一個協議。特別是該方法應該返回BOOL - (BOOL)shouldLoadGameKitViewController: (UIViewController*) viewController;,我想用-performSelector來調用它。這裏有一點,如果方法不能立即返回,我無法從代表那裏得到答案。
我使用NSInvocation來做到這一點,但是是冗長的,是否存在其他方式?

[WITH代碼更新]現在我使用的調用
注意的是,線程檢查部是不是還實現。評論也給了警告

部分
- (void) dispatchToDelegate: (SEL) selector withArg: (id) arg error: (NSError*) err 
{ 
    NSMethodSignature *methodSig = [[self class] instanceMethodSignatureForSelector:selector]; 
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 
    [invocation setTarget:self.delegate]; 
    if([self.delegate respondsToSelector: selector]) 
    { 
     if(arg != NULL) { 
      [invocation setArgument:&arg atIndex:2];  
      [invocation setArgument:&err atIndex:3];  

//   [_delegate performSelector: selector withObject: arg withObject: err]; 

     }else { 
      [invocation setArgument:&err atIndex:2];  
//   [_delegate performSelector: selector withObject: err]; 

     } 
     [invocation invoke]; 

    } 
    else 
     DLog(@"Method not implemented in the delegate"); 
} 

[解的排序還未得到檢驗]

- (BOOL) dispatchToDelegate: (SEL) selector withArg: (id) arg error: (NSError*) err 
{ 
    NSMethodSignature *methodSig = [[self class] instanceMethodSignatureForSelector:selector]; 
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; 
    [invocation setTarget:self.delegate]; 
    BOOL result = NO; 
    if([self.delegate respondsToSelector: selector]) 
    { 
     if(arg != NULL) { 
      [invocation setArgument:&arg atIndex:2];  
      [invocation setArgument:&err atIndex:3];  

//   [_delegate performSelector: selector withObject: arg withObject: err]; 

     }else { 
      [invocation setArgument:&err atIndex:2];  
//   [_delegate performSelector: selector withObject: err]; 

     } 
     if ([NSThread isMainThread]) { 
      [invocation invoke];   
     } 
     else{ 
      [invocation performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:YES]; 
     } 
     [invocation getReturnValue:&result]; 
    } 
    else 
     NSLog(@"Missed Method"); 
    return result; 
} 

使用NSMethodSignature方法,可以擋起來,並索要回報類型。我仍然沒有測試,但它應該取得訣竅。

+1

爲什麼你需要'performSelector'?如果你有一個符合協議的委託,你可以直接調用該方法:'BOOL b = [self.delegate shouldLoadGameKitViewController:...]'。 –

+0

因爲在調用主線程之前我有一個方法,因爲你不知道在哪裏調用這個塊。 – Andrea

+0

所以你正在替換'performSelectorOnMainThread'?也許你可以顯示相關的代碼,然後它更容易幫助。 –

回答

-1

儘量讓這個以避免泄漏或「未知選擇發送到實例」的問題:

SEL selector = NSSelectorFromString(@"methodName::"); 
if ([obj respondsToSelector:selector]) 
    [obj performSelector:selector [email protected][args,array]]; 
+0

它並沒有使消失消失 – Andrea

-1

可以使用dispatch_sync代替dispatch_async有立即執行塊(你的代碼將被阻止,直到塊回報)。

另一種替代方法是暫時禁止警告,如this answer中所述。

+0

這樣就會導致死鎖http://stackoverflow.com/questions/10330679 /如何在主隊列上同步分派 - 沒有死鎖 – Andrea

+0

dispatch_async可能會立即執行。 'async'和'sync'唯一的區別在於塊保證在後者返回前完全執行。 – bbum