5 Stimmen

Objective C NSString* Eigenschaft behalten Zählung oddity

Ich habe die folgende Beispielklasse:

Test.h:

@interface Test : UIButton {
    NSString *value;
}
- (id)initWithValue:(NSString *)newValue;
@property(copy) NSString *value;

Test.m:

@implementation Test
@synthesize value;
- (id)initWithValue:(NSString *)newValue {
    [super init];   
    NSLog(@"before nil value has retain count of %d", [value retainCount]);
    value = nil;
    NSLog(@"on nil value has retain count of %d", [value retainCount]);
    value = newValue;
    NSLog(@"after init value has retain count of %d", [value retainCount]);
    return self;
}

Das Ergebnis ist die folgende Ausgabe:

2008-12-31 09:31:41.755 Concentration[18604:20b] before nil value has retain count of 0
2008-12-31 09:31:41.756 Concentration[18604:20b] on nil value has retain count of 0
2008-12-31 09:31:41.757 Concentration[18604:20b] after init value has retain count of 2147483647

Ich nenne es so:

Test *test = [[Test alloc] initWithValue:@"some text"];

Sollte der Wert nicht eine Beibehaltungszahl von 1 haben? Was übersehe ich?

Vielen Dank für Ihre Hilfe.

22voto

Chris Hanson Punkte 53324

Achten Sie nicht auf die Anzahl der Wiederholungen. Sie sind nicht nützlich und führen Sie nur in die Irre - Sie können nicht sicher sein, dass kein anderer ein Objekt behält, dass ein Objekt, das Sie von irgendwoher erhalten, nicht gemeinsam genutzt wird.

Konzentrieren Sie sich stattdessen auf Objektbesitz und folgen Sie den Regeln für die Cocoa-Speicherverwaltung auf den Punkt gebracht. Auf diese Weise wird Ihre Speicherverwaltung korrekt sein, unabhängig davon, welche Optimierungen Cocoa im Hintergrund für Sie vornimmt. (Zum Beispiel kann die Implementierung von -copy wie eben -retain für unveränderliche Objekte).

Außerdem ist es kritisch um den Unterschied zwischen Eigenschaften Ihrer Objekte und Instanzvariablen innerhalb Ihrer Objekte. Im Code Ihrer Frage weisen Sie einer Instanzvariablen einen Wert zu. Diese Instanzvariable ist genau das: eine Variable. Eine Zuweisung an sie verhält sich wie jede andere Variablenzuweisung. Um die Eigenschaft zu verwenden, müssen Sie entweder die Punktsyntax oder die Klammersyntax verwenden, um die Setter-Methode der Eigenschaft tatsächlich aufzurufen:

self.value = newValue;     // this is exactly equivalent to the next line
[self setValue:newValue];  // this is exactly equivalent to the previous line

Der für die Punktsyntax und die Klammersyntax erzeugte Code ist identisch, und beide greifen nicht direkt auf die Instanzvariable zu.

11voto

Stefan Tannenbaum Punkte 266

Sie geben eine wörtliche Zeichenkette ein. Der Compiler weist sie wahrscheinlich im statischen Speicher zu und setzt die Retain-Zahl auf den maximal möglichen Wert.

Versuchen Sie stattdessen eine dynamisch zugewiesene Zeichenkette und sehen Sie, was passiert.

NSString* string = [[NSString alloc] initWithString: @"some text"];
Test* test = [[Test alloc] initWithValue: string];

0 Stimmen

Es wird im statischen Speicher zugewiesen, obwohl ich das Attribut copy für die Eigenschaft verwende?

0 Stimmen

Wenn Sie die Eigenschaft verwenden wollen, müssen Sie "self.value = whatever" sagen, anstatt nur "value = whatever", was einfach die Instanzvariable zuweist.

2 Stimmen

Getan.. gleichen Fehler. Ich habe auch versucht, mit dem dynamischen String-Code oben.

4voto

Sie haben einen Verweis auf eine unveränderliche Zeichenfolge. Die Zuweisung braucht den Wert (die Zeichenkettendaten) nicht zu kopieren, da er unveränderlich ist. Wenn Sie eine veränderbare Operation durchführen, wie value = [newValue uppercaseString], dann sollten die Bits in value kopiert werden, und value's retain count wird erhöht.

1 Stimmen

Dies geht nicht wirklich auf die grundlegenden Probleme mit dem Code des ursprünglichen Posters ein: Er hält sich nicht an die Regeln der Speicherverwaltung, und er weist direkt einer Instanzvariablen zu, anstatt über die Eigenschaft zu gehen.

3voto

Stephen Darlington Punkte 50435

Sie geben eine String-Konstante ein, die nicht wirklich freigegeben werden kann. Ich denke, dass 2147483647 wahrscheinlich UINT_MAX ist, was im Grunde bedeutet, dass das Objekt nicht freigegeben werden kann.

0 Stimmen

Wird mit dem Attribut "Kopie" nicht eine neue Kopie erstellt, die sich nicht im statischen Speicher befindet?

0 Stimmen

Was würde das bringen? Sie können den Wert nicht ändern, also können Sie genauso gut auf den statischen Speicher verweisen. Vielleicht sollten Sie versuchen, den Typ in NSMutableString zu ändern, um zu sehen, ob Sie das gleiche Verhalten erhalten.

0 Stimmen

Es ist möglich, dass eine -kopie das Original tatsächlich -erhält, wenn das Original unveränderlich ist, so dass eine -kopie garantiert identisch wäre.

3voto

Kristopher Johnson Punkte 78933

Ich glaube, Sie wollen das tun:

self.value = newValue;

was den Eigenschaftssetzer aufruft und die Kopie auslöst. "value = newValue" weist der Instanzvariablen einfach einen Zeigerwert zu.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X