неочевидное уменьшение количества ссылок - PullRequest
2 голосов
/ 26 октября 2011

Xcode Analyze пожаловался на то, что я неправильно уменьшил счетчик ссылок в строке с пометкой «эта строка».это кажется немного странным, поскольку не было очевидно, что эта строка уменьшает счетчик ссылок.

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    UIImage * image = [[UIImage alloc] initWithData:receivedData];
    if (image == nil) {
        image = [UIImage imageNamed:@"null.bmp"];
    }
    self.itemImage.image = image; //this line
    self.promotion.image = image; 
    [image release];
}

Ответы [ 3 ]

5 голосов
/ 26 октября 2011

Это слегка хитрая вещь; Понятно, что это вызывает путаницу. Два пути здесь приводят к image хранению объектов с разными статусами владения и, таким образом, с разным количеством ссылок.

Пройдя через if, вы получите image с объектом, который не принадлежит вашему коду.

UIImage * image = [[UIImage alloc] initWithData:receivedData];
// If |initWithData:| succeeds, the object in |image| is owned, because you
// called |alloc| to create it.
if (image == nil) {
    image = [UIImage imageNamed:@"null.bmp"];
    // This object is _not_ owned by your code and you must not send
    // |release| to it.
}
// ... the setter lines are irrelevant to the reference count of |image|.

[image release];
// This is only okay if |initWithData:| succeeded and you have ownership
// of |image|.

Я думаю, что анализатор показывает неправильную строку, точно так же, как компилятор будет пожаловаться на пропущенную точку с запятой пятью строками позже.

Чтобы решить эту проблему, можно сохранить изображение, полученное с imageNamed: Вы не можете просто не отправить release, потому что вы делаете владеете image в одном случае, и вам нужно должным образом отказаться от этой собственности. Я также предложил бы добавить комментарий об отправке retain, чтобы вы помнили восемь месяцев спустя, почему вы это сделали.

Лучше, чем это, как предложено ниже неподражаемым Bavarious, и, как я думаю, вы сами уже поняли, было бы автоматически выпустить изображение alloc и удалить более позднюю строку release.

1 голос
/ 19 ноября 2011

Полагаю, Джош в основном это понимал, но я бы уточнил ...

[UIImage imageNamed:@"null.bmp"];

Это создаст URemage с автоматическим выпуском.

Но ...

UIImage * image = [[UIImage alloc] initWithData:receivedData];

создает переменную, которая требует явного освобождения. Таким образом, в зависимости от того, получили ли вы данные (возможно, сеть отключена), у вас будут разные правила владения в зависимости от того, было ли изображение выделено с явным требованием к выпуску или с автоматическим выпуском. Таким образом, [выпуск изображения] будет неправильным, если данные не были получены.

1 голос
/ 26 октября 2011

Я не эксперт Objective-C, но похоже, что вы перезаписываете содержимое sefl.itemImage.image с помощью изображения локального указателя, поэтому уменьшаете одну ссылку до того, что было сохранено в self.itemImage.image доприсваивание.

Я не думаю, что локальное изображение, являющееся нулевым или ненулевым, имеет какое-либо отношение к нему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...