ObjC-Memory Management: Difference between revisions

From Medien Wiki
(created)
 
Line 23: Line 23:


== Beispiel ==
== Beispiel ==
=== Interface (file.h) ===
<source lang="objc">
@interface MyClass:NSObject {
    NSString *name;
    int age;
    id delegate;
}
@property (nonatomic, retain) id delegate;
// Hinweis: name und age würden normalerweise auch einfacher als properties verwendet!
-(NSString*)name;
-(void)setNewName:(NSString*)newName;
-(int)age;
-(void)setAge:(int)newAge;
@end
</source>
=== Implementation (file.m) ===
<source lang="objc">
#import "file.h"
@implementation MyClass
@synthesize delegate;
-(id)init {
    self = [super init];
    if(self) {
        [self setName:@"Barnie"];
        [self setAge:30];
    }
}
-(NSString*)name { return name; }
-(void)setName:(NSString*)newName {
    if(newName != name) {
        [name release];
        [newName retain];
        name = newName;
    }
}
-(int)age { return age; }
-(void)setAge:(int)newAge { age = newAge; }
-(void)dealloc {
    [delegate release]; // retain-property!
    [self setName:nil]; // release wird im Setter gesendet!
    // age braucht keinen release weil int ist kein Objekt!
}
@end
</source>
Fragen:
* was ist ein Accessor?
* was passiert im dealloc bei: <tt>name = nil;</tt>?
* wo ist der Unterschied:
** [self setName:nil];
** self.name = nil;
** name = nil;


== Regeln ==
== Regeln ==

Revision as of 16:48, 18 February 2010

Retain-Count

Das Memory-Management von Cocoa basiert auf einem Retain-Count Mechanismus. Anders als z.B. bei C (malloc & free) ist es relativ unrelevant, ob man ein Objekt erstellt hat, oder es erhält, weil man damit arbeiten möchte.

Jedes Objekt hat einen sog. retain count, der normalerweise bei der Erstellung des Objektes (z.B. mit alloc oder copy) einen Wert von 1 hat. Wenn nun dieses Objekt von einem anderen Objekt als seinem Eigentümer für längere Berechnungen oder als eigene Instanz-Variable benötigt wird, so kann man [obj retain] aufrufen. Damit steigt der retain-count dieses Objektes um 1 auf 2. Das Objekt wird gelöscht (bzw. der [obj dealloc] aufgerufen), wenn der retain-count auf 0 zurück geht.

Wichtig: Der Programmierer muss dafür sorgen, dass seine retain/release bzw. alloc/release bzw. copy/release Aufrufe ausgeglichen sind. Ansonsten kommt es zu Leaks (Zombie-Objekte) oder zu einem Crash, wenn ein Objekt per release freigegeben wird, das es nicht mehr gibt.

Alloc/Init/Copy/Retain

NSString *newString = [[NSString alloc] init];
NSString *anotherString = [newString copy];
NSString *aThirdString = [anotherString retain];
  • alloc (allocate) reservier Speicher für ein Objekt (und macht sonst nichts weiter, deshalb sieht man alloc immer nur in Verbindung mit init: [[obj alloc] init] oder [[obj alloc] initWithSomething:...]
    • alloc erstellt ein Objekt mit einem anfänglichen retain-count von 1
  • init (initialize) initialisiert das Objekt
    • init erhöht den retain-count nicht!
  • copy kopiert das Objekt und erstellt ein neues, eigenständiges Objekt mit einem eigenen Speicherbereich
    • copy erstellt ein Objekt mit einem anfänglichen retain-count von 1
  • retain sorgt dafür, dass das Objekt auf jeden Fall erhalten bleibt. Es wird kein neues Objekt erstellt.
    • retain erhöht den retain-Count um 1.

Beispiel

Interface (file.h)

@interface MyClass:NSObject {
    NSString *name;
    int age;
    id delegate;
}

@property (nonatomic, retain) id delegate;

// Hinweis: name und age würden normalerweise auch einfacher als properties verwendet!

-(NSString*)name;
-(void)setNewName:(NSString*)newName;

-(int)age;
-(void)setAge:(int)newAge;

@end


Implementation (file.m)

#import "file.h"

@implementation MyClass

@synthesize delegate;

-(id)init {
    self = [super init];
    if(self) {
        [self setName:@"Barnie"];
        [self setAge:30];
    }
}

-(NSString*)name { return name; }
-(void)setName:(NSString*)newName {
    if(newName != name) {
        [name release];
        [newName retain];
        name = newName;
    }
}

-(int)age { return age; }
-(void)setAge:(int)newAge { age = newAge; }

-(void)dealloc {
    [delegate release]; // retain-property!
    [self setName:nil]; // release wird im Setter gesendet!
    // age braucht keinen release weil int ist kein Objekt!
}

@end

Fragen:

  • was ist ein Accessor?
  • was passiert im dealloc bei: name = nil;?
  • wo ist der Unterschied:
    • [self setName:nil];
    • self.name = nil;
    • name = nil;

Regeln

  • Genau geregelte Verantwortlichkeiten:
  • Wer alloc, new, copy, retain verwendet, muss auch jeweils 1x release senden
  • Wer nicht alloc, new, copy, retain aufruft, darf nicht release aufrufen
  • Niemals dealloc selbst aufrufen (es sei denn man überschreibt die Methode und ruft [super dealloc] auf!

Links




Diese Seite ist Teil des Werkmoduls iOS Development von Michael Markert für Interface Design / Fakultät Medien an der Bauhaus-Universität Weimar.