Освобождение/доступ к различным объектам с одинаковым именем в разных классах

Я новичок в objective-c (и все, что касается Apple, если на то пошло).

Я разрабатываю приложение iOS и сталкивался с ошибкой, которая казалась мне очень интересной. В основном, я начал работать в VC (LoginViewController), а где-то по пути я бы нажал другой VC на мой контроллер навигации (MyProfileViewController).

Но когда я вернусь через стек обратно в LoginViewController, прикосновение к любому объекту на экране вызовет ошибку EXEC_BAD_ACCESS. После некоторой царапины головы я решил изменить имена таблиц в представлениях (оба моих ViewControllers содержали UITableView, определенные в их соответствующих файлах .m, и оба из которых я назвал "myTable" ).

Оказалось, что для моего приложения, помимо того, что оно способствует плохой читаемости (вам не нужно меня бить по этому вопросу), назвав обе таблицы тем же самым, что и вызывало крах. Поэтому я предполагаю, что когда MyProfileViewController был освобожден, он также выпустил "myTable" из LoginViewController.

С обычными ошибками я понимаю свою ошибку, стараюсь учиться на ней и двигаться дальше. Но это не имеет для меня никакого смысла, почему это создает катастрофу в первую очередь. Какие-нибудь идеи? Для справки, здесь, как я определял и освобождал UITableView в обоих ViewControllers.

@implementation MyProfileViewController//same format as LoginViewController

UITableView* myTable;//It since been renamed to something more descriptive

//code...

-(void)viewDidLoad{
    [super viewDidLoad];
    myTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStyleGrouped];
    [myUpdateTable setDataSource:self];
    [myTable setDelegate:self];
    [self.view addSubview:myTable];
}

//code...

-(void)dealloc{
    [myTable release];
    [super dealloc];
}

Ответ 1

Во-первых, правильно ли я прочитал ваш код, что ваш UITableView не определен в @interface? Если это так, вы определили myTable как глобальную переменную. Это не очень хорошая идея, хотя я удивлен, что компоновщик не жаловался, если вы использовали одну и ту же глобальную переменную в двух файлах .m(но это, безусловно, объясняло бы, почему использование одного и того же имени вызвало проблемы). Вы действительно хотите, чтобы ваш UITableView был переменной экземпляра. Вы можете определить переменную частного экземпляра в верхней части вашего .m файла следующим образом (поместите это перед @implementation):

@interface MyProfileViewController ()
{
    UITableView* _myTable;
}
@end

Если вы это сделаете, то не имеет значения, будет ли имя вашей переменной экземпляра в одном классе быть таким же, как в другом классе. Объем переменной экземпляра класса ограничен этим классом. (Кстати, в стиле, многие люди предисловивают свои переменные экземпляра класса с подчеркиваниями, как правило, чтобы отличать их от свойств класса и локальных переменных.)

Второй (и не связанный с вашим исходным вопросом), я предлагаю высвободить в viewDidLoad, таким образом:

- (void)viewDidLoad {
    [super viewDidLoad];

    _myTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStyleGrouped];
    [_myTable setDataSource:self];
    [_myTable setDelegate:self];
    [self.view addSubview:_myTable];
    [_myTable release];
}

(И, очевидно, удалите оператор release из вашего dealloc.)

Нет причин откладывать release: когда вы выделяете /init, у него есть счет сохранения +1, когда вы addSubview получаете счетчик +2, а когда вы отпускаете, вы просто возвращаетесь релиз возвращается к +1 (это означает, что он не будет отменен, потому что self.view сохраняет его, но когда представление в конечном итоге освободит его, ваше табличное представление будет автоматически отменено для вас). Тем не менее, есть веские причины не откладывать его (ваш исходный код будет протекать, если вы получили didReceiveMemoryWarning после нажатия на новый контроллер представления).

Если вы используете ARC, эта проблема глупого управления памятью обычно очищается для вас, но, учитывая, что вы не используете ARC, вам может потребоваться настроить, где вы отпустите.