Frage

Dies ist ein kleines Detail, aber jedes Mal wenn ich faul Last etwas, das ich auf ihn erwischt. Sind beide Methoden akzeptabel? Ist entweder besser? Es sei angenommen, dass die Variable hat die Eigenschaft beibehalten.

Methode # 1

(AnObject *)theObject{
    if (theObject == nil){
        theObject = [[AnObject createAnAutoreleasedObject] retain];
    }
    return theObject;
}

Methode 2

(AnObject *)theObject{
    if (theObject == nil){
        self.theObject = [AnObject createAnAutoreleasedObject];
    }
    return theObject;
}

Als erstes bin ich nicht sicher, ob es in Ordnung ist innerhalb eines Zugriffs eines anderen Zugriffsfunktion zugreifen (nicht sehen, warum nicht, obwohl). Aber es scheint, wie die Klassenvariable Einstellung ohne Setter durchlaufen gleich schlecht sein könnte, wenn die Setter tun etwas Besonderes (oder wenn die Eigenschaft auf etwas geändert wird neben behalten und der Getter nicht aktiviert ist).

War es hilfreich?

Lösung

Beide sind eigentlich ziemlich zerbrechlich und nicht identisch, je nachdem, was Kunden der Klasse tun. sie identisch zu machen ist einfach genug - siehe unten - aber so dass es weniger zerbrechlich härter ist. So ist der Preis für faule Initialisierung (und warum ich versuche generell faul Initialisierung auf diese Weise, lieber zu behandeln Initialisierung von Subsystemen als Teil der Gesamtanwendung staatlicher Verwaltung zu vermeiden).

Mit # 1, Sie vermeiden die Setter und somit alles um die Änderung zu beobachten wird die Änderung nicht sehen. Mit „Beobachten“, ich beziehe ich speziell auf Schlüssel-Wert-Beobachtung (einschließlich Cocoa Bindungen, die KVO verwenden die Benutzeroberfläche automatisch zu aktualisieren).

Mit # 2, werden Sie die Änderungsbenachrichtigung auslösen, die Benutzeroberfläche zu aktualisieren und ansonsten genau so, wie wenn der Setter genannt wurde.

In beiden Fällen Sie ein Potential für eine unendliche Rekursion, wenn die Initialisierung des Objekts den Getter aufruft. Dazu gehört, wenn ein Beobachter für den alten Wert als Teil der Änderungsmitteilung fragt. Tu das nicht.

Wenn Sie eine Methode verwenden wollen, sollten Sie sorgfältig die Konsequenzen. Man hat das Potenzial, die App in einem inkonsistenten Zustand zu verlassen, weil eine Zustandsänderung einer Immobilie nicht benachrichtigen und das andere hat das Potenzial für Deadlock.

Besser das Problem vollständig zu vermeiden. Siehe unten.


Betrachten (Garbage Collection auf, Standard Cocoa Kommandozeilen-Tool:

#import <Foundation/Foundation.h>

@interface Foo : NSObject
{
    NSString *bar;
}
@property(nonatomic, retain) NSString *bar;
@end
@implementation Foo
- (NSString *) bar
{
    if (!bar) {
        NSLog(@"[%@ %@] lazy setting", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
        [self willChangeValueForKey: @"bar"];
        bar = @"lazy value";
        [self didChangeValueForKey: @"bar"];
    }
    return bar;
}

- (void) setBar: (NSString *) aString
{
    NSLog(@"[%@ %@] setting value %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), aString);
    bar = aString;
}
@end

@interface Bar:NSObject
@end
@implementation Bar
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
{
    NSLog(@"[%@ %@] %@ changed\n\tchange:%@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), keyPath, change);
}
@end

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    Foo *foo = [Foo new];
    Bar *observer = [Bar new];
    CFRetain(observer);
    [foo addObserver:observer forKeyPath:@"bar"
             options: NSKeyValueObservingOptionPrior | NSKeyValueObservingOptionNew
             context:NULL];
    foo.bar;
    foo.bar = @"baz";
    CFRelease(observer);

    [pool drain];
    return 0;
}

Dies gilt nicht hängen. Es spuckt:

2010-09-15 12:29:18.377 foobar[27795:903] [Foo bar] lazy setting
2010-09-15 12:29:18.396 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
    change:{
    kind = 1;
    notificationIsPrior = 1;
}
2010-09-15 12:29:18.397 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
    change:{
    kind = 1;
    new = "lazy value";
}
2010-09-15 12:29:18.400 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
    change:{
    kind = 1;
    notificationIsPrior = 1;
}
2010-09-15 12:29:18.400 foobar[27795:903] [Foo setBar:] setting value baz
2010-09-15 12:29:18.401 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
    change:{
    kind = 1;
    new = baz;
}

Wenn Sie NSKeyValueObservingOptionOld in die Liste der Optionen für die Beobachtung hinzuzufügen waren, ist es sehr viel kostet hängen.

Kommen wir zurück auf eine Bemerkung, die ich früher gemacht; die beste Lösung ist auf nicht faul Initialisierung als Teil Ihrer Getter / Setter . Es ist zu fein gekörnt. Sie sind besser weit weg Ihren Objektgraph Zustand auf einer höheren Ebene der Verwaltung und als Teil davon, einen Zustandsübergang hat, die im Wesentlichen aus dem „Yo ist! Ich werde jetzt dieses Subsystem verwenden! Warm, dass Bad Boy up! " Das macht die verzögerte Initialisierung.

Andere Tipps

sind solche Verfahren, nie identisch. Die erste ist richtig, während der zweite ist falsch ! Ein Getter kann nie will/didChangeValueForKey: nennen und damit auch nicht die Setter. Dies führt Rekursion auf unendlich wenn diese Eigenschaft beobachtet wird.

Und außerdem gibt es keine Statusänderung zu beobachten, wenn das Element initialisiert wird. Sie fragen Sie Ihr Objekt für die theObject und Sie es. Wenn diese erstellt wird, ist eine Implementierung Detail und keine Sorge für die Außenwelt.

Wenn Sie die Eigenschaft Setter-Methode kennen ein Standardhalt Setter ist, sind sie identisch. Wenn nicht, müssen Sie, ob die andere Verhalten Setter entscheiden sollte während dieser Operation aufgerufen werden. Wenn Sie nicht wissen, ist es am sichersten, die Setter zu verwenden, da sein Verhalten wichtig sein kann. Sie nicht schwitzen.

Diese beiden sind im Grunde identisch, es ist wirklich nur an Ihnen, zu wählen, welche am besten für Ihren Fall ist. Sie beschrieben schon wirklich die Vor / Nachteile über die Eigenschaft Syntax.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top