Frage

Ich habe eine NSDocument, die die folgende Struktur:

@interface MyDocument : NSDocument
{
    NSMutableArray *myArray;

    IBOutlet NSArrayController *myArrayController;
    IBOutlet MyView *myView;
}
@end

instanziiert ich die NSArrayController und die MyView in MyDocument.xib, und haben die Verbindungen zu den Datei-Besitzer (MyDocument) gemacht, so dass ich bin mir ziemlich sicher, dass aus der Sicht von Interface Builder, ich alles richtig gemacht haben.

Die Schnittstelle für MyView ist einfach:

@interface MyView : NSView {
    NSMutableArray *myViewArray;
}
@end

Nun, in MyDocument windowControllerDidLoadNib, ich habe den folgenden Code:

- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
    [super windowControllerDidLoadNib:aController];
    [myArrayController setContent:myArray];
// (This is another way to do it)    [myArrayController bind:@"contentArray" toObject:self withKeyPath:@"myArray" options:nil];

    [myView bind:@"myViewArray" toObject:myArrayController withKeyPath:@"arrangedObjects" options:nil];
}

Im Debugger Ich habe festgestellt, dass myViewArray ist ein NSControllerArrayProxy, so scheint es, dass meine programmatische Bindung korrekt ist. Allerdings, wenn ich versuche, Objekte in MyView Methoden zum MyView myViewArray hinzufügen, erscheinen sie nicht die MyDocument des myArray zu aktualisieren. Ich habe die beiden folgenden Ansätze versucht:

[myViewArray addObject:value];
[self addMyViewArraysObject:value];

(Der zweite Ansatz führt zu einem Compiler-Fehler, wie erwartet, aber ich dachte, dass die Objective-C-Laufzeit würde „implementieren“ diese Methode pro meinem begrenzten Verständnis von KVO).

Gibt es etwas falsch mit, wie ich versuche, myViewArray zu aktualisieren? Gibt es etwas falsch mit meiner programmatischen Bindung? (Ich versuche, dies programmatisch zu tun, weil MyView eine benutzerdefinierte Ansicht ist, und ich möchte nicht eine IB-Palette für sie schaffen.)

War es hilfreich?

Lösung

Das Problem ist, dass Sie Ihre Array direkt sind mutiert. Implementieren Sie indiziert Accessormethoden und diejenigen nennen.

KVO überschreibt Ihre Zugriffsmethoden (solange Sie bestimmte Formate ) und die notwendigen Meldungen postet. Sie haben nicht das bekommen, wenn Sie direkt zu Ihrem Array sprechen; alles auf die Eigenschaft gebunden werden nicht wissen, dass Sie die Eigenschaft geändert haben, wenn Sie es ausdrücklich sagen. Wenn Sie Ihre Zugriffsmethoden verwenden, sagt KVO die anderen Objekte für Sie.

Die einzige Zeit, nicht Ihre Accessormethoden (synthetisiert oder auf andere Weise) zu verwenden ist in init und dealloc, da Sie zu einem Halb inited oder -deallocked Objekt würde sprechen.

Wenn Sie Ihre eigene Zugriffsmethoden verwenden das Array zu mutieren und dadurch bekommen die freien KVO-Benachrichtigungen, die Dinge sollten einfach funktionieren:

  • Die Aussicht, wenn seine Eigenschaft mutiert, wird die Array-Controller automatisch benachrichtigt, die ihre content Eigenschaft mutiert, die den Controller benachrichtigt.
  • Ihr Controller, wenn seine Eigenschaft mutiert, wird die Array-Controller automatisch benachrichtigt, die ihre arrangedObjects Eigenschaft mutiert, die die Ansicht teilt.

Andere Tipps

Ich kann zwei Möglichkeiten sehen Sie hier:

Zuerst geht instanziert das NSMutableArray Objekt (und loslassen) in Ihrer MyDocument Klasse? Es soll wie folgt aussehen:

- (id)init
{
    if ((self = [super init]) == nil) { return nil; }
    myArray = [[NSMutableArray alloc] initWithCapacity:0];
    return self;
}

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

Zweitens habe erklären Sie myViewArray als Eigenschaft in MyView? Es soll wie folgt aussehen:

// MyView.h:
@interface MyView : NSView
{
    NSMutableArray * myViewArray;
}
@property (assign) NSMutableArray * myViewArray;
@end
// MyView.m:
@implementation MyView

@synthesize myViewArray;

@end

Other than that, es sieht für mich wie Sie alle die Bindung richtig gemacht haben.

Update: Wie über den NSArrayController mit Artikel zum Array hinzuzufügen:

// MyView.h:
@interface MyView : NSView
{
    NSMutableArray * myViewArray;
    IBOutlet NSArrayController * arrayController;
}
@property (assign) NSMutableArray * myViewArray;
- (void)someMethod;
@end
// MyView.m:
@implementation MyView

@synthesize myViewArray;

- (void)someMethod
{
    id someObject = [[SomeClass alloc] init];
    [arrayController addObject:[someObject autorelease]];
}

@end

Das Problem scheint zu sein, dass ich hatte MyView die myViewArray auf die NSArrayController des arrangedObjects Eigenschaft für verbindlich statt dessen content Eigenschaft.

Wenn arrangedObjects Bindung, fand ich, dass das eigentliche Objekt, auf dem durch myViewArray war eine Instanz von NSControllerArrayProxy . Ich habe keine definitive Antwort auf die Frage finden, was das Objekt tatsächlich tut, wenn ich auf sie online mehr Informationen gesucht. Allerdings deuten die Code-Beispiele Ich fand, dass NSControllerArrayProxy sollte an Komfort belichten für den Zugriff auf die Eigenschaften von Objekten im Array , anstatt die Objekte (im Array) selbst. Aus diesem Grunde glaube ich, dass ich mich geirrt bei der Bindung an arrangedObjects.

Die Lösung wurde auf statt MyView des myViewArray auf die die NSArrayController binden content Eigenschaft:

- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
    [super windowControllerDidLoadNib:aController];

    [myArrayController setContent:myArray];
    [myView bind:@"myViewArray" toObject:myArrayController withKeyPath:@"content" options:nil];
}

Obwohl dies scheint zu funktionieren, ich bin nicht 100% sicher, dass es richtig ist, zu binden content in diesem Fall. Wenn jemand kann etwas Licht auf programmatisch auf die verschiedenen Eigenschaften eines NSArrayController Bindung, würde ich Kommentare zu dieser Antwort begrüßen. Danke.

Zunächst einmal gibt es nichts falsch mit der Bindung an arrangedObjects: ein NSTableColumn, zum Beispiel, sollte sein Gehalt an arrangedObjects nur gebunden hat, und ihre content zu arrangedObjects.someProperty.

Der häufigste Fehler ist arrangedObjects als Inhalt eines Arraycontroller zu betrachten, sondern dass, wie Sie, zu Trauer gesehen haben führen: arrangedObjects eine Darstellung der Art und Weise ist der Arraycontroller zur Zeit die Objekte in ihrem Inhalt angeordnet hat, nicht den Inhalt selbst.

Das heißt, die Art und Weise um ein Array zu einem Arraycontroller zu binden:

[self.myArrayController bind:NSContentArrayBinding 
 toObject:self
 withKeyPath:@"myView.myViewArray" 
 options:nil]; 

Sind Sie sicher, nebenbei gesagt, Ihrer Ansicht nach braucht die myViewArray zu halten? Das in der Regel fällt unter der Verantwortung eines Controllers oder Modellobjekt.

Jetzt können Sie Objekte hinzufügen, indem Aufruf addObject auf dem Arraycontroller , denn das ist in der Verantwortung des Controllers ist.

[self.myArrayController addObject: anObject]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top