Вы должны выпустить IBOulets в dealloc? - PullRequest
26 голосов
/ 07 октября 2009

Нужно ли выпускать IBOulets в dealloc? Я не уверен в этом, потому что я не делал alloc, и обычно вы выпускаете только для того, что вы называли alloc. Кто-нибудь знает?

Ответы [ 7 ]

35 голосов
/ 07 октября 2009

Ваш IBOutlets, вероятно, @properties. Если они есть, и у вас есть retain в качестве атрибута, то вам нужно выпустить в -dealloc

Другими словами:

@interface MyViewController : UIViewController {
    IBOutlet UITableView *myTable;
}

@property (nonatomic, retain) IBOutlet UITableView *myTable;

@end

Вам придется набрать [myTable release]; в вашем деле.

Если вы создаете новое приложение на основе навигации в XCode и смотрите appdelegate.h:

@interface Untitled1AppDelegate : NSObject <UIApplicationDelegate> {

    UIWindow *window;
    UINavigationController *navigationController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;

@end

и dealloc для appdelegate.m:

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

Ключевым моментом здесь являются такие строки:

@property (nonatomic, retain) IBOutlet UIWindow *window;

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

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

9 голосов
/ 08 октября 2009

Если вы просто используете IBOutlet в своем интерфейсе, вам НЕ нужно их выпускать. Причина в том, что если вы явно не сохраните их в своем коде, они просто устанавливаются. Они держатся вокруг, потому что вид есть. Очевидно, что если вы также используете свойства и сохраняете их, вам нужно освободить на dealloc.

8 голосов
/ 07 октября 2009

Речь идет не о IBOutlet, а о вашей декларации. Если вы используете мастер нового проекта в XCode, вы, вероятно, получите такой код в своем заголовочном файле.

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;

Как видите, в заголовочном файле есть ключевое слово retain . Следуя рекомендациям по управлению памятью, вы ДОЛЖНЫ освободить все, что у вас есть (вызывая alloc, copy, retain и т. Д.). И у вас есть сохранить в вашем коде, тогда вы должны выпустить it.

Кроме того, мастер уже добавил вам код выпуска.

- (void)dealloc {
    [tabBarController release];
    [window release];
    [super dealloc];
}
2 голосов
/ 16 октября 2011

Чтобы ответить на дополнительный вопрос Джо Д'Андреа. Вы можете использовать self.label = nil;. Потому что он вызывает setLabel, который генерируется автоматически:

- (void)setLabel:(UILabel *)input
{
   [label autorelease];
   label = [input retain];
}

Как вы можете видеть, текущий label будет выпущен, тогда nil назначен метке.

Но убедитесь, что вы не пишете это как label = nil. Это не будет работать. Потому что вам нужно вызвать автоматически сгенерированный метод доступа к меткам.

2 голосов
/ 07 октября 2009

Как вы сказали, вы должны освободить все, что вы выделили сами (с alloc или copy). Это работает по-другому: вы не должны освобождать объекты Какао, которые вы не выделяли самостоятельно (некоторые функции CoreFoundation выделяют, и вы несете ответственность за их освобождение, но здесь это не так).

Если вы не распределили свой IBOutlet, вам не нужно его выпускать, если, конечно, по какой-то причине вы не сохранили его где-то.

1 голос
/ 16 августа 2011

Если это ваш BlahViewController.h:

//  BlahViewController.h
#import <UIKit/UIKit.h>
@interface BlahViewController
{
    IBOutlet UINavigationBar *navigationBar;
}
@property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;

@end

Тогда это будет ваш dealloc в BlahViewController.m:

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

Однако, если это ваш BlahViewController.h:

//  BlahViewController.h
#import <UIKit/UIKit.h>
@interface BlahViewController
{
    IBOutlet UINavigationBar *navigationBar;
}

@end

Тогда это будет ваш dealloc в BlahViewController.m:

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

И, наконец, если это ваш BlahViewController.h:

//  BlahViewController.h
#import <UIKit/UIKit.h>

@interface BlahViewController
{
    IBOutlet UINavigationBar *navigationBar;
    IBOutlet MKMapView *map;
}

@property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;

@end

Тогда это будет ваш dealloc в BlahViewController.m:

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

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

1 голос
/ 15 октября 2009

Вот что я делал в отношении IBOutlet объектов (вместе с файлом NIB):

@interface MyViewController : UIViewController {
  UILabel *label;
}

@property (nonatomic, retain) IBOutlet UILabel *label;

@end

@implementation MyViewController
@synthesize label;

- (void)setView:(UIView *)aView {
  if (!aView) {
    // view is being set to nil
    // set outlets to nil to get the benefit of the didReceiveMemoryWarning!
    self.label = nil;
  }
  // Invoke super's implementation last
  [super setView:aView];
}

- (void)viewDidLoad {
  [super viewDidLoad];
}

- (void)viewDidUnload {
  // Release any retained subviews of the main view.
  // e.g. self.myOutlet = nil;
  self.label = nil;
}

- (void)didReceiveMemoryWarning {
  // Releases the view if it doesn't have a superview.
  [super didReceiveMemoryWarning];

  // Release any cached data, images, etc that aren't in use.
}

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

Дополнительный вопрос: имеет ли смысл использовать self.label = nil в dealloc или должен * * явно вызываться release (например, чтобы статический анализатор был доволен)?

Полагаю, в этот момент мы все равно уходим, поэтому нет необходимости устанавливать для наших объектов IBOutlet значение nil.

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