2009-10-07 3 views
26

Müssen Sie IBoulets in dealloc freigeben? Ich bin mir da nicht sicher, weil ich das Alloc nicht gemacht habe und normalerweise nur für etwas freigegeben habe, auf das du Alloc ankommst. Weiß jemand?Müssen Sie IBoulets in dealloc freigeben?

+0

Duplizieren: http://stackoverflow.com/questions/61838/do-i-need-to-release-xib-resources – Casebash

Antwort

35

Ihre IBOutlets sind wahrscheinlich @properties. Wenn sie sind, und Sie haben retain als Attribut, dann brauchen Sie in -dealloc

Mit anderen Worten zu lösen:

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

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

@end 

Sie zu [myTable release]; in Ihrem dealloc haben.

Wenn Sie eine neue Navigation Based App in Xcode machen, und suchen Sie im appdelegate.h:

@interface Untitled1AppDelegate : NSObject <UIApplicationDelegate> { 

    UIWindow *window; 
    UINavigationController *navigationController; 
} 

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

@end 

und der dealloc für appdelegate.m:

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

Der Schlüssel ist daran zu sehen Hier sind Zeilen wie diese:

Wenn dort ein behalten ist, bedeutet das, dass die Eigenschaft ist " Besitz "durch Ihren Code und Sie müssen es freigeben.

Natürlich gibt es andere Möglichkeiten, wie die IBOutlets nicht als Eigenschaften deklarieren oder als Eigenschaften deklarieren, ohne sie zu behalten. Ich finde, dass ich es in den meisten Fällen bevorzuge, Eigenschaften zu behalten, die ich dann explizit freigeben muss. Ein Beispiel hierfür ist, wenn Sie von einem Ansichtscontroller zu einem anderen wechseln. Wenn ein Ansichtscontroller geschlossen wird, werden seine Ansichten entfernt und sie werden freigegeben. Alle IBOutlet UILabels in dieser Ansicht werden ebenfalls freigegeben, wenn sie nicht beibehalten werden. Das bedeutet, dass wenn ich zur alten Ansicht zurück blicke, ich meine Etiketten und Kontrollen auf ihre letzten Werte zurücksetzen muss, wenn ich sie einfach gespeichert hätte, wenn ich nur das IBOutlet behalten würde.

2

Wie Sie gesagt haben, sollten Sie alles, was Sie selbst zugewiesen haben, freigeben (mit alloc oder copy). Es funktioniert auch anders herum: Sie sollten keine Cocoa-Objekte freigeben, die Sie nicht selbst zugewiesen haben (einige CoreFoundation-Funktionen weisen sie zu und Sie sind für deren Freigabe verantwortlich, aber das ist hier nicht der Fall).

Wenn Sie Ihr IBOutlet nicht zugewiesen haben, müssen Sie es nicht freigeben, es sei denn, Sie haben es aus irgendeinem Grund irgendwo gespeichert.

+1

Schlüsselwort ist ("es sei denn .. du hast es irgendwo"), was passieren wird, wenn Sie Verwenden Sie eine Eigenschaft (nicht atomisch, behalten). – Fraggle

8

Es geht nicht um IBOutlet, es geht um Ihre Deklaration. Wenn Sie einen neuen Projektassistenten in Xcode verwenden, erhalten Sie in der Header-Datei wahrscheinlich einen Code wie diesen.

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

Sie sehen können, gibt es Schlüsselwort in der Header-Datei beibehalten. Gemäß der Speicherverwaltungsrichtlinie MÜSSEN Sie alles freigeben, was Sie behalten (indem Sie alloc aufrufen, kopieren, behalten usw.). Und Sie haben behalten in Ihrem Code dann müssen Sie Release es.

Zusätzlich fügt der Assistent bereits einen Release-Code für Sie hinzu.

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

Wenn Sie nur IBOutlet in Ihrer Schnittstelle verwenden, müssen Sie sie NICHT freigeben. Grund ist, dass, wenn Sie sie nicht explizit in Ihrem Code behalten, sie nur gesetzt werden. Sie bleiben herum, weil die Aussicht da ist. Offensichtlich müssen Sie, wenn Sie auch Eigenschaften verwenden und diese beibehalten, auf dealloc freigeben.

+0

Steht diese Antwort nicht im Widerspruch zu der obigen? Müssen Sie oder nicht? So verwirrt. – erotsppa

+0

Nein, es ist nicht widersprüchlich: "Natürlich, wenn Sie auch Eigenschaften verwenden und behalten, müssen Sie auf dealloc freigeben". – mahboudz

+0

Als Test, erstellen Sie eine neue Nav-basierte App in Xcode. Sie werden sehen, wie sie IBOutlets in ihrem Dealloc freigeben. – mahboudz

1

Hier ist, was ich habe im Hinblick auf IBOutlet Objekte zu tun (in Verbindung mit einer NIB-Datei):

@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]; 
} 

Side Frage: Macht es mehr Sinn macht self.label = nil in dealloc zu verwenden, oder muss release explizit sein genannt (zum Beispiel, um den statischen Analysator glücklich zu halten)?

Ich nehme an, an diesem Punkt sind wir sowieso auf dem Weg nach draußen, also müssen wir unsere IBOutlet-Objekte nicht auf null setzen.

1

Wenn dies Ihr BlahViewController.h ist:

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

@end 

Dann würde dies Ihr dealloc in BlahViewController.m sein:

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

jedoch, wenn dies Ihre BlahViewController.h ist:

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

@end 

Dann wäre dies Ihre dealloc in BlahViewC ontroller.m:

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

Und schließlich, wenn dies Ihr BlahViewController.h ist:

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

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

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

@end 

Dann würde dies Ihr dealloc in BlahViewController.m sein:

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

Kurz gesagt, Wenn Sie es als eine Eigenschaft mit retain deklarieren, dann müssen Sie es freigeben.

2

Um die Nebenfrage von Joe D'Andrea zu beantworten. Sie können self.label = nil; verwenden. Weil es setLabel ruft, die automatisch generiert wird:

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

Wie Sie die aktuelle label dann freigegeben werden sehen nil zu Etikett zugeordnet ist.

Aber stellen Sie sicher, dass Sie es nicht als label = nil schreiben. Das wird nicht funktionieren. Da müssen Sie die automatisch generierte Label-Accessor-Methode aufrufen.

Verwandte Themen