2012-03-30 3 views
2

Ich habe mehrere Panels, die NSTextField Steuerelemente enthalten, die an Eigenschaften innerhalb der Datei Besitzer Objekt gebunden sind. Wenn der Benutzer ein Feld bearbeitet und dann Tab drückt, um zum nächsten Feld zu gelangen, funktioniert es wie erwartet. Wenn der Benutzer jedoch Tab nicht drückt und nur die OK-Schaltfläche drückt, wird der neue Wert nicht in dem Objekt File Owner Objekt festgelegt.Cocoa: Vermeiden von "Updates kontinuierlich" in Steuerelement bindet

Um dies zu umgehen habe ich Updates kontinuierlich in der Bindung, aber das muss teuer sein (EDIT: oder zumindest ist es unelegant).

Gibt es eine Möglichkeit, die Bindeaktualisierung zu erzwingen, wenn die Schaltfläche OK gedrückt wird, anstatt fortlaufend zu aktualisieren??

+0

Was lässt Sie denken, dass "Updates Continuously" teuer ist? Ist es? Hast du ein Profil? –

+0

Nun, nein, wie üblich Rob, aber es setzt Werte in meiner C++ - Hauptbibliothek, die die Konstruktion von 'std :: string'-Objekten und die Konvertierung zwischen' NSString'-Objekten beinhaltet. Es scheint einfach unelegant und ich dachte, es muss einen besseren Weg geben. – trojanfoe

+0

Ich stimme zu, es ist nur so, dass Annahmen über die Leistung nie eine gute Idee ist. Vorzeitige Optimierung ist böse! –

Antwort

6

Sie haben Recht, dass Sie die Option für fortlaufende Aktualisierungen nicht verwenden müssen.

Wenn Sie Bindings verwenden (was Sie sind), dann sollten Sie die -commitEditing-Methode der NSController-Unterklasse aufrufen, die die Bindung verwaltet. Normalerweise würden Sie dies in Ihrer Methode tun, die das angezeigte Blatt schließt.

-commitEditing weist den Controller an, die Bearbeitung im aktiven Steuerelement zu beenden und die aktuellen Änderungen an das gebundene Objekt zu übergeben.

Es ist eine gute Idee, dies immer dann aufzurufen, wenn Sie eine Persistenzoperation ausführen, z. B. eine Sicherung.

+0

Also bedeutet das, dass Sie ein * outlet * für jedes Steuerelement im Bereich benötigen und "commitEditing" für alle aufrufen müssen, bevor Sie das Fenster schließen? Oder gibt es einen einfacheren Weg dies zu implementieren? – trojanfoe

+0

Sie rufen 'commitEditing' nicht auf den Steuerelementen auf, Sie rufen es auf dem' NSController' auf, an den die Steuerelemente gebunden sind. Dies könnte ein 'NSArrayController',' NSTreeController' oder nur ein einfacher 'NSObjectController' sein. Wenn Sie Ihre Steuerelemente direkt an ein Modellobjekt und nicht über einen NSObjectController binden, sollten Sie Ihre Bindungen so ändern, dass ein NSObjectController als Zwischenobjekt verwendet wird. Der Hauptgrund dafür ist, dass der 'NSObjectController' das 'NSEditorRegistration'-Protokoll verwendet, um den Steuerelementen zu sagen, dass sie die Bearbeitung beenden sollen, während eine einfache Bindung dies nicht tut. –

+0

Hmmm, interessant. Das ist neu für mich und überhaupt nicht erwähnt in dem Buch, in dem ich anfänglich Cocoa-Programmierung gelernt habe. Ich werde das untersuchen. Gibt es ein Problem mit meinem Ansatz (wie in meiner Antwort beschrieben) oder wird dies als * hack * betrachtet? – trojanfoe

2

Die Lösung hierfür ist das Beenden der Bearbeitung in der Aktionsmethode, die über die Schaltfläche OK aufgerufen wird. Da der Bereich eine Unterklasse von NSWindowController ist, ist der NSWindow leicht zugänglich, aber in Ihrem Code müssen Sie möglicherweise die NSWindow über ein Steuerelement erhalten, das Sie an den Controller gebunden haben; zum Beispiel NSWindow *window = [_someControl window].

Unten ist die Implementierung meiner okPressed Aktionsmethode.

Zusammenfassend glaube ich, das ist eine besser Lösung Einstellung in den gebundenen Kontrollen Kontinuierlich aktualisiert.

- (IBAction)okPressed:(id)sender 
{ 
    NSWindow *window = [self window]; 
    BOOL editingEnded = [window makeFirstResponder:window]; 
    if (!editingEnded) 
    { 
     logwrn(@"Unable to end editing"); 
     return; 
    } 

    if (_delegateRespondsToEditComplete) 
    { 
     [_delegate detailsEditComplete:&_mydetails]; 
    } 
} 
0

Obwohl das wirklich alt ist, stimme ich absolut nicht mit der Annahme überein, dass diese Frage basiert.

Zählig Aktualisierung die Bindung ist absolut nicht teuer. Ich nehme an, Sie könnten denken, dass dies den Wert kontinuierlich aktualisiert und versteht, dass "regelmäßig auf einem Intervall basiert".

Aber das ist nicht wahr. Dies bedeutet nur, dass es aktualisiert wird, wenn Sie den gebundenen Wert ändern. Das heißt, wenn Sie etwas in ein TextView eingeben, wird es während des Schreibens aktualisiert. Das ist es, was Sie in dieser Situation wollen.

+0

Danke für den Kommentar; aber das ist alles, was es ist; Es ist keine Antwort. – trojanfoe