[НЕ СЕ ДУБЛИРА: прочетете добре въпроса и вече дадените отговори, аз вече ги прочетох]
Изправен съм пред този проблем, трябва да заменя метода -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