Сохранить количество IBOutlets - PullRequest
1 голос
/ 20 января 2010

Хотя при кодировании всегда возникали одни и те же вопросы, касающиеся сохранения количества IBOutlets: Сохранить счет после разархивирования объекта из NIB? Когда использовать свойство @ для IBOutlet? Сохранить или назначить при настройке? Различия между Mac и iPhone?

Итак, я прочитал Жизненный цикл объекта пера из документации Apple. Некоторые тестовые приложения на Mac и iPhone дали мне странные результаты. Тем не менее, я записал несколько правил, как справиться с этой проблемой, чтобы оставаться довольным во время кодирования, но теперь хотел узнать у сообщества и выслушать ваше мнение и опыт:

  1. Всегда создавайте IBOutlet для объектов верхнего уровня. Для объектов не верхнего уровня, если необходимо (необходим доступ).
  2. Всегда предоставляйте свойство для IBOutlets следующим образом (и освобождайте их при необходимости!):
    • Объекты верхнего уровня на Mac:
      • @ свойство (неатомное, assign ) IBOutlet SomeObject * someObject;
      • @ synthesize someObject;
      • [self.someObject release ];
    • Объекты не верхнего уровня на Mac ( без выпуска ):
      • @ свойство (неатомное, назначить ) IBOutlet NSWindow * window;
      • @ synthesize someObject;
    • Объекты верхнего уровня на iPhone (должны быть сохранены):
      • @ свойство (неатомное, сохранить ) IBOutlet SomeObject * someObject;
      • @ synthesize someObject;
      • [self.someObject выпуск ];
    • Объекты не верхнего уровня на iPhone (следует сохранить ):
      • @ свойство (неатомное, сохранение) IBOutlet UIWindow * window;
      • @ синтезировать окно;
      • [self.window release ];

Примечания:

  • На Mac и iPhone розетки подключаются с помощью сеттера, если он доступен.
  • Объекты верхнего уровня: «не [...] не имеют объекта»
  • Объекты не верхнего уровня: «любые объекты, у которых есть родительский или владеющий объект, например представления, вложенные в иерархии представлений».

Таким образом, вопрос будет: это правильная и хорошая практика?

Надеюсь, вы сможете одобрить или исправить его.

Ответы [ 6 ]

10 голосов
/ 21 января 2010

Всегда имейте свои перья . Владелец файла будет подклассом NSWindowController или NSViewController (в Mac OS X) или UIViewController (на iPhone), и используйте @property (retain) IBOutlet для всех своих выходов, выполняя соответствующие выпуски в вашем контроллере подкласс -dealloc метод.

Этот шаблон будет отлично работать на на Mac OS X и iPhone OS, потому что NSWindowController и NSViewController в Mac OS X принимают на себя неявное владение объектами верхнего уровня (и отказываются от него) что в их собственных -dealloc методах), и iPhone OS не берет на себя никаких явных прав собственности на объекты верхнего уровня во время загрузки пера.

1 голос
/ 30 июня 2010

Из Apple's Doc , упомянутых выше:

Как для Mac OS X, так и для UIKit, рекомендуемый способ управления объектами верхнего уровня в файле пера - создать для них выходыобъект-владелец файла, а затем определите методы установки для сохранения и освобождения этих объектов по мере необходимости.Методы установки дают вам подходящее место для включения кода управления памятью даже в ситуациях, когда ваше приложение использует сборщик мусора.Один из простых способов реализовать ваши методы установки - создать объявленное свойство (используя синтаксис @property) и позволить компилятору создать их для вас.Для получения дополнительной информации о том, как определить свойства, см. Язык программирования Objective-C.

В противном случае используйте @property (nonatomic, retain) IBOutlet * outletName;

1 голос
/ 20 января 2010

Объекты верхнего уровня: "не [...] не владеющий объектом"

Nix. Объекты верхнего уровня принадлежат владельцу файла, который является владельцем файла, поскольку он владеет всеми объектами верхнего уровня в файле.

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

Если вы считаете, что это противоречит документации, которую вы цитировали, давайте пройдемся по всему абзацу:

Объекты в nib-файле изначально создаются с счетом сохранения 1. Однако при перестроении иерархии объектов AppKit автоматически освобождает любые объекты, у которых есть родительский или владеющий объект, например представления, вложенные в иерархии представлений.

Таким образом убивая свои собственные владения. Загрузчик пера не хочет владеть вашими объектами.

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

Другими словами, он передает вам право собственности.

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

Как для Mac OS X, так и для UIKit, рекомендуемый способ управления объектами верхнего уровня в nib-файле - создать для них выходы в объекте-владельце файла, а затем определить методы установки для сохранения и освобождения этих объектов при необходимости.

Но если вы сделаете это, объект останется живым даже после того, как вы освободите свое владение им.

Думаю, я пойду сообщу об ошибке. (Правка: Готово. X-radar: // problem / 7559755) По крайней мере, загрузчик пера не должен передавать два удержания, что он делает в моем тестовом приложении (10.5.8 и 10.6.1).

0 голосов
/ 20 января 2010

1) В общем, зачем вам объект верхнего уровня без IBOutlet, чтобы все равно указывать на него? Это требование никогда не казалось очень ограничительным.

2) Я думаю, что вы получили правильные настройки для iPhone. Вы также можете использовать свойство присвоения на iPhone, что делает то, что вы ожидаете ... но в целом после большого использования я предпочитаю использовать свойства сохранения, поэтому я на 100% уверен, когда считаю объект освобожденным ( особенно с помощью метода viewDidUnload для реализации).

Кроме того, просто замечание, что не стоит называть [self.property release]. Это оставляет ссылку нетронутой, но потенциально недействительной, если что-то еще когда-либо также освобождает объект ... либо произнесите self.property = nil, либо (лучше) установите для переменной базового класса значение nil напрямую, без использования свойств в операторах dealloc (чтобы избежать любых возможные побочные эффекты в dealloc).

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

// in .m file
@interface MyClass ()
@property (nonatomic, retain) IBOutlet UIView *myPrivateView;
@end

@implementation MyClass
@synthesize myPrivateView;
.....
0 голосов
/ 20 января 2010

Вы должны следовать стандартным рекомендациям по управлению памятью. Если ваша розетка подключена к retain ed свойству, вы должны разблокировать его в сообщении -dealloc.

И да, любые объекты верхнего уровня, не сохраняемые другими объектами, обычно должны храниться вами.

0 голосов
/ 20 января 2010

Я могу написать свое мнение о разработке iPhone NIB:

  • Если вы используете IB, то используйте как можно больше IBOutlets (иногда вы не знаете иерархию представлений при создании NIB - это может быть динамически) или вообще не используете их - иначе будет беспорядок
  • Используйте свойства, только если вы хотите получить доступ к представлениям снаружи Контроллера представления (если они должны быть общедоступными)
  • AFAIK, нет необходимости управлять памятью для IBOutlets

Надеюсь, это поможет ...

...