[НЕ ДУБЛИРУЙТЕ: внимательно прочитайте вопрос и уже данные ответы, я их уже читал]
Я столкнулся с этой проблемой, мне нужно заменить метод -performSelector
, так как он вызывает это предупреждение в компиляторе с ARC
PerformSelector может вызвать утечку, потому что его селектор неизвестен.
Я знаю, что есть разные вопросы по этой теме:
и я также знаю о методах, позволяющих избежать этого предупреждения.
Иногда в качестве решения я обнаруживал, что наиболее рекомендуемым советом является использование dispatch_async(dispatch_get_main_queue(),^(void) { WHATEVER });
, но, насколько я знаю, диспетчеризация потребует выполнения блока при следующем запуске. цикл, -performSelector
(без задержки) выполняется сразу.
К чему эта мысленная мастурбация? Представьте, что вы используете новый метод Gamekit для аутентификации, игровой комплект может отправить вам внутри блока аутентификации контроллер представления, чтобы заставить пользователя выполнить какую-либо операцию (например, создать идентификатор, войти в систему и т. д.). Было бы полезно предупредить пользователя, если он/она хочет увидеть этот контроллер представления. Для этого и прочего я пишу протокол. В частности, этот метод должен возвращать BOOL - (BOOL)shouldLoadGameKitViewController: (UIViewController*) viewController;
, я бы хотел вызвать его, используя -performSelector
. В том-то и дело, что если метод не вернётся сразу, я не смогу получить ответ от делегата.
Я использую NSInvocation, чтобы это произошло, но он многословен, существует ли какой-то другой способ?
[ОБНОВЛЕНИЕ С КОДОМ]
Обратите внимание, что теперь, когда я использую вызов, часть проверки потока еще не реализована. В комментарии есть та часть, которая выдала предупреждение
- (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, можно настроиться и запросить тип возвращаемого значения. Я все еще не тестировал, но это должно было помочь.
performSelector
? Если у вас есть делегат, соответствующий протоколу, вы можете вызвать метод напрямую:BOOL b = [self.delegate shouldLoadGameKitViewController:...]
. - person Martin R   schedule 03.06.2013performSelectorOnMainThread
? Возможно, вы можете показать соответствующий код, тогда легче помочь. - person Martin R   schedule 03.06.2013performSelectorOnMainThread
илиdispatch_(a)sync
. В обоих случаях метод не может вернуть значение вызывающему потоку, если вы не дождетесь завершения, но это может легко привести к взаимоблокировке. - person Martin R   schedule 03.06.2013