Хорошая практика / Плохая практика - Указатели и установочные значения - Цель C - PullRequest
2 голосов
/ 24 марта 2011

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

Мне нужно было, чтобы мой контроллер вида мог установить собственный заголовок для его UIBarButtonItem в зависимости от того, какой новый контроллер представления он собирался поместить в стек контроллера навигации.Вместо того, чтобы иметь условный код для проверки, существует ли self.navigationItem.backBarButtonItem каждый раз, когда я пытался установить его новый заголовок (потому что по умолчанию, если вы его не создаете, self.navigationItem.backBarButtonItem равен nil), я сделал это:

Это работает, но кто-нибудь может указать, почему я не должен этого делать: у меня есть пользовательский метод получения, который лениво создает кнопку возврата панели навигации:

- (UIBarButtonItem *)myBackButton {
if (!myBackButton) {
    myBackButton =  [[[UIBarButtonItem alloc] initWithTitle:self.title style:UIBarButtonItemStylePlain target:nil action:nil] retain];
    self.navigationItem.backBarButtonItem = myBackButton;
}
return myBackButton;

}

Сейчасв остальной части файла .m всякий раз, когда я хочу изменить заголовок кнопки «назад» (например, перед тем, как поместить новый контроллер представления в стек контроллера навигации), я просто делаю:

self.myBackButton.title = @"Some Custom Title";

или:

self.myBackButton.title = self.title;

И я считаю, что это работает, потому что self.myBackButton и self.navigationItem.backBarButtonItem указывают на один и тот же объект.Является ли этот тип косвенной установки объектов целесообразным?Если нет, то что было бы лучшим способом передачи сценария с кнопками?

Большое спасибо, Мэтт

Ответы [ 4 ]

2 голосов
/ 24 марта 2011

Вам следует прочитать Руководство по управлению памятью, чтобы узнать о alloc, retain, ...

Вы выделяете кнопку возврата (= она принадлежит вам), и вы ее тоже сохраняете (= вы владеете ею дважды)таким образом, вам также придется дважды вызывать release.

Нет необходимости лениво создавать кнопку возврата, это небольшой кусок памяти, и я предполагаю, что вы всегда хотите, чтобы он был виден.Лучше сделать это в методе init вашего UIViewController.

Правильный путь - это ...

self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:self.title style:UIBarButtonItemStylePlain target:nil action:nil] autorelease];

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

  • каждый метод, имя которого начинается с alloc, new, copy или mutableCopy, создает объект, который является вашим (= вы переходите во владение, вы должны освободить его где-то)
  • , если вы хотите освободить его(прочитайте об отказе от владения), вы должны вызвать release или autorelease для этого объекта, хорошей практикой является также установка ivar на nil
1 голос
/ 24 марта 2011

Вы, вероятно, хотите изменить этот метод на что-то вроде этого.

- (UIBarButtonItem *)myBackButton {
    if (!myBackButton) {
        myBackButton =  [[[UIBarButtonItem alloc] initWithTitle:self.title style:UIBarButtonItemStylePlain target:nil action:nil] autorelease];
    }
return myBackButton;
}

тогда, где-то еще (вероятно, в вашем viewDidLoad / появиться) вызов

self.navigationItem.backBarButtonItem= self.myBackButton;

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

также, когда вы устанавливаете его в качестве элемента backbuttonItem, он все равно сохраняется этим.

Стоит отметить, что при доступе к свойствам через точечную нотацию вы фактически проходите через сеттеры и геттеры. т.е.

self.myBackButton.title =@"title";

совпадает с

[[self myBackButton] setTitle:@"title"];

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

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

0 голосов
/ 25 марта 2011

Да, вы не совсем понимаете правила управления памятью, но больше к вашему вопросу: нет, не беспокойтесь о реализации этого средства доступа к кнопке назад, уже есть средство доступа к кнопке назад, и оно self.navigationItem.backBarButtonItem.

Этот метод, который вы предложили, - это ленивые средства доступа, которые вы используете, когда у вас есть объект, который не нужен до тех пор, пока средства доступа не будут вызваны.Он скрывает детали создания объекта для вызывающих, которые не должны знать.

Однако в этой ситуации объект, кнопка, необходим контроллеру навигационного представления в нужное время и должен быть создан там, гдеэто имеет смысл.Это в контроллере представления, я думаю, что кнопка должна быть создана либо в init, loadView, или, возможно, viewWillAppear.В этой ситуации детали создания кнопок должны быть явными в любом из этих мест, где они есть.

Так что извлекайте тот метод доступа, где бы вы ни хотели использовать self.myBackButton.titleиспользуйте self.navigationItem.backBarButtonItem и, наконец, убедитесь, что вы инициализируете его в месте, которое вызывается, прежде чем вам когда-либо понадобится доступ к нему (часто к вашему init).

0 голосов
/ 24 марта 2011

Ваш вопрос сводится к следующему: что происходит с кнопкой «Назад» после ее нажатия - когда снимается вид, которым она управляет. Проверьте счетчик удерживания вашей кнопки возврата в этих ситуациях. Если он остается стабильным, все в порядке (при условии, что никакие другие модули в вашей программе не назначают разные экземпляры кнопки возврата). В противном случае вам придется каждый раз создавать новую кнопку «назад».

...