Почему происходит утечка памяти в GameCenterManager.m?

Я использую Game Center в своем приложении и обнаружил, что файл gamecentermanager.m вызывает утечку памяти:

- (void) callDelegate: (SEL) selector withArg: (id) arg error: (NSError*) err
{
assert([NSThread isMainThread]);
if([delegate respondsToSelector: selector])
{
    if(arg != NULL)
    {
        [delegate performSelector: selector withObject: arg withObject: err];
    }
    else
    {
        [delegate performSelector: selector withObject: err];
    }
}
else
{
    NSLog(@"Missed Method");
}
}

Утечка происходит (согласно предупреждающим треугольникам компилятора), потому что селектор performSelector (обоих) неизвестен. есть 2 вещи, которые я хочу знать

1) Я скопировал это прямо из примера на веб-сайте Apple, поэтому не будет ли код содержать ошибку, если Apple его создаст?

2) Как я могу это исправить?

Так же, как FYI, я использую Xcode 4.3.1, используя компилятор LLMV 3.1 и стандартную (armv7) архитектуру. Я тоже пользуюсь АРК.

Если вам нужна какая-либо другая информация, просто дайте мне знать и заранее спасибо.


person cory ginsberg    schedule 20.03.2012    source источник


Ответы (1)


Проблема здесь в том, что ARC не может сказать, какова семантика управления памятью метода, который вы вызываете с помощью -performSelector:withObject:. В MRR это не имело значения, потому что вызывающий код должен был обрабатывать его соответствующим образом (например, освобождая возвращаемое значение, если это был принадлежащий объект). Но в ARC компилятор должен знать эту информацию, чтобы быть верной. Я не помню, каково его поведение по умолчанию с -performSelector:withObject:, возможно, это просто обращение к нему как к не принадлежащей ссылке, и в этом случае вы на самом деле не пропускаете.

Самый простой способ справиться с таким шаблоном делегата - по-прежнему использовать -respondsToSelector:, но затем просто вызывать метод напрямую, например.

if ([_delegate respondsToSelector:@selector(foo:)]) {
    [_delegate foo:self];
}

В вашем случае сам метод на самом деле не знает, что такое селектор. Лучше всего, вероятно, полностью отказаться от этого метода и позволить его бывшим вызывающим объектам общаться с делегатом.

person Lily Ballard    schedule 20.03.2012
comment
Нельзя ли добавить фальшивую категорию в NSObject, объявив этот метод? Просто для уточнения семантики... - person nielsbot; 20.03.2012
comment
@nielsbot: проблема не в отсутствии объявления метода. Проблема в том, что компилятор даже не знает, какой метод он пытается вызвать, независимо от объявления, потому что он использует динамический селектор для его вызова. - person Lily Ballard; 20.03.2012
comment
Я решил больше не использовать файл GameCenterManager, который я скопировал из Apple, из-за того, что вы сказали. Спасибо за ответ. - person cory ginsberg; 21.03.2012