Предупреждение анализатора о некорректном уменьшении счетчика ссылок

Я только что установил Xcode 4 и открыл более раннюю версию своего приложения. Анализатор сообщает для этой строки:

[self.myViewControllerObject release];

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

Я не включил ARC для своего проекта.

Когда я анализирую v2.0 своего приложения в Xcode 3.2.5, он не показывает никакой потенциальной ошибки.

Заголовок:

        @class MyViewController;

        MyViewController *myViewControllerObject;

        @property ( nonatomic , retain )  MyViewController *myViewControllerObject; 

Выполнение:

        #import "MyViewController.h"

        @synthesize myViewControllerObject;

При нажатии кнопки у меня есть:

ПОПРОБУЙТЕ 1:

self.myViewControllerObject = [[MyViewController alloc]initWithNibName:@"MyViewController" bundle:nil]; 

[self.navigationController pushViewController:self.myViewControllerObject animated:YES];


[self.myViewControllerObject release];

ПОПРОБУЙТЕ 2:

MyViewController *temp = [[MyViewController alloc]initWithNibName:@"MyViewController" bundle:nil];  

self.myViewControllerObject = temp;

[temp release];

[self.navigationController pushViewController:self.myViewControllerObject animated:YES];


[self.myViewControllerObject release];

ПОПРОБУЙТЕ 3:

self.myViewControllerObject = [[MyViewController alloc]initWithNibName:@"MyViewController" bundle:nil]; 

[self.navigationController pushViewController:self.myViewControllerObject animated:YES];

В методе dealloc я его отпускаю:

[self.myViewControllerObject release];

person Vijay-Apple-Dev.blogspot.com    schedule 10.11.2011    source источник


Ответы (3)


Предупреждение исходит от того, что вы вызываете release для свойства через метод доступа: когда вы делаете [self.myViewControllerObject release], вы фактически вызываете метод доступа myViewControllerObject, а затем release для возвращаемого значения. Поскольку имя метода не начинается с new, copy или mutableCopy, вы не владеете возвращаемым им объектом, следовательно, вам не разрешено release его использовать.

Решение состоит в том, чтобы никогда не вызывать release для возвращаемого значения этого метода доступа, поэтому в основном ваша попытка № 2 была в порядке:

MyViewController *temp = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];  
self.myViewControllerObject = temp;
[self.navigationController pushViewController:temp animated:YES];
[temp release];

Но в dealloc не используйте аксессор, а:

[myViewControllerObject release];

Если вам нужно release myViewController отличное от dealloc, назначьте nil через сеттер:

self.myViewControllerObject = nil;

Правка: дополнительные сведения по этому вопросу см. в разделе Руководство по расширенному управлению памятью от Apple.

person Arkku    schedule 10.11.2011

Контроллер навигации управляет жизненным циклом контроллеров представления, которые вы к нему добавляете. Таким образом, когда вы нажимаете контроллер представления, вы передаете «владение». Однако нет никаких причин, по которым вы не можете также поддерживать ссылку на контроллер представления. Попробуйте этот порядок:

    self.myViewControllerObject = [[MyViewController alloc]initWithNibName:@"MyViewController" bundle:nil]; 

    [self.myViewControllerObject release];

    [self.navigationController pushViewController:self.myViewControllerObject animated:YES];

Выделенные объекты начинаются с единицы сохранения. Присвоение значения вашему свойству 'retain' увеличивает счетчик сохранения на единицу. Вы должны оставить только одно удержание для объекта, чтобы правильно его отпустить. Но поскольку вы начинаете с двух, можно отпустить его до того, как вы передадите его навигационному контроллеру. Предупреждение компилятора, которое вы видите, это просто предупреждение, а не всегда доказательство того, что вы делаете что-то строго неправильно. Не имеет значения, пройдете ли вы его, а затем отпустите, но указанный выше порядок должен его избегать.

person Jacob Jennings    schedule 10.11.2011
comment
перед нажатием myviewcontroller мы не должны его отпускать. Тогда это будет nil. поэтому navigationcontroller будет нажимать nil . - person Vijay-Apple-Dev.blogspot.com; 10.11.2011
comment
@AppleVijay: во-первых, release не присваивает nil ссылке, а во-вторых, свойство myViewControllerObject определяется с помощью retain, поэтому присвоение self.myViewControllerObject из alloc приводит к тому, что объект сохраняет счетчик 2, поэтому он все еще равен 1 после release. Но вы можете заменить autorelease, если вам от этого станет легче. знак равно - person Arkku; 10.11.2011
comment
@Arkku хороший улов, я пробовал также эти два выпуска. но все еще показывает ту же проблему. есть идеи? - person Vijay-Apple-Dev.blogspot.com; 10.11.2011
comment
@Arkku, если ты прав, тогда посмотри мою ПОПРОБУЙ 2. Это то же самое, что ты сказал. - person Vijay-Apple-Dev.blogspot.com; 10.11.2011
comment
Вы пробовали порядок, который я рекомендовал? «Попробуйте 2» по-прежнему срабатывает после того, как вы нажмете на контроллер представления. Вам нужно освободить только один раз, сразу после того, как вы назначите контроллер представления своему свойству myViewControllerObject. - person Jacob Jennings; 10.11.2011
comment
@AppleVijay Да, ваша попытка 2 в порядке, за исключением последнего release на self.myViewControllerObject, см. Мой ответ. - person Arkku; 10.11.2011

Когда я использовал версию XCode 4 Beta, возникла проблема. Но когда я попробовал это в версии XCode 4, предупреждение Analyzer не появилось. Я благодарю всех, кто участвовал, чтобы помочь мне. Спасибо за ваше время.

person Vijay-Apple-Dev.blogspot.com    schedule 11.07.2014