Hallo,
momentan schreibe ich meinen Vokabeltrainer um. Bisher habe ich die Daten/Views etc. ohne ArrayController verwaltet (alles mit dataSources gemacht). Dies möchte ich nun ändern. Dabei bin ich auf ein Problem gestoßen, welches ich nicht lösen kann.
Ich schildere die momentane Situation und dieses nicht definierbare Verhalten. Bin mir sicher, dass ihr einige Tipps parat habt.
Die Daten werden momentan in einer Datenbank gespeichert. Zu Beginn lade ich die Daten (z.B einige Karteikarten) in ein Model (FileCard). Dieses Model ist KVC-entsprechend. Zusätzlich habe ich einen ArrayController, welcher FileCard Objekte enthalten kann. Via Code füge ich dann die FileCard Objekte, die vom ArrayController verwaltet werden sollen wie folgt hinzu:
Das funktioniert alles wunderprächtig. Nun habe ich ja allerdings zwei verschiedene Dinge... einen ArrayController mit FileCards, der diese in einer TableView anzeigt und eine Datenbank, in der die Daten gespeichert werden. Ändert der Benutzer nun einen Eintrag in der TableView, so wird diese Änderung folglich auch im ArrayController getan. Aber nicht in der Datenbank... dh ich muss die "edit"-Events irgendwie abfangen und ebenfalls in die Datenbank schreiben, damit Inhalt des ArrayController + Inhalt der Datenbank übereinstimmen, sodass der Benutzer beim nächsten Start der Applikation keinen Schreck bekommt.
Soweit so gut...
NSTableView hat leider keine Delegate Methode, die mich über die Art und Weise der vorgenommenen Bearbeitung einer Zeile in NSTableView informiert. Ich habe lediglich eine entsprechende Methode gefunden, die NSTableView aufruft... tap tap... Subclassen ist angesagt...
"Abfangen" möchte ich:
- (BOOL)textShouldEndEditing:(NSText *)textObject
von NSTableView und als Delegate verfügbar machen. Ob das in Cocoa der richtige Weg ist - k/A...
Aber ich habe es mal gemacht:
Alles anzeigen
Nun müsste ich in meinem TableViewDelegate ja mittels "textShouldEndEditingDelegate" über Editierversuche meines gelieben Benutzers doch informiert werden - und ja - es klappt...
In meinem TableViews Delegage habe ich folgende Funktion:
Diese gibt mir einen Zeige auf die momentan selektierte Karteikarte zurück. fileCardsController ist der NSArrayController mit den FileCard Objekten.
Ob das so ganz der richtige Weg ist - bin ich mir nicht sicher... aber seis drum...
In meinem TableView Delegate kann ich nun mit meinem eigenen Delegate die Editierversuche abfangen und versuchen in die Datenbank zu schreiben.
Gesagt getan.
Und was geschieht beim editieren? Die Daten werden richtig in der Datenbank auf den neusten Stand gebracht aber in der Zelle, die bearbeitet steht nun plötzlich der Wert der Zelle über der bearbeiteten. (siehe 1. Screenshot)
Komisch dabei ist: Falls ich eine weniger dynamische Version meines Quelltextes verwende:
dann klappt es wunderbar, wie erwartet (siehe 2. Screenshot) Ich habe nur eine Zeile verändert.
[fileCard setFrontSide:[textObject string]];
wurde zu
[fileCard setFrontSide:@"FUCK"];
Was habe ich übersehen?
Der, der den Fehler findet bekommt 10 Euro
momentan schreibe ich meinen Vokabeltrainer um. Bisher habe ich die Daten/Views etc. ohne ArrayController verwaltet (alles mit dataSources gemacht). Dies möchte ich nun ändern. Dabei bin ich auf ein Problem gestoßen, welches ich nicht lösen kann.
Ich schildere die momentane Situation und dieses nicht definierbare Verhalten. Bin mir sicher, dass ihr einige Tipps parat habt.
Die Daten werden momentan in einer Datenbank gespeichert. Zu Beginn lade ich die Daten (z.B einige Karteikarten) in ein Model (FileCard). Dieses Model ist KVC-entsprechend. Zusätzlich habe ich einen ArrayController, welcher FileCard Objekte enthalten kann. Via Code füge ich dann die FileCard Objekte, die vom ArrayController verwaltet werden sollen wie folgt hinzu:
Das funktioniert alles wunderprächtig. Nun habe ich ja allerdings zwei verschiedene Dinge... einen ArrayController mit FileCards, der diese in einer TableView anzeigt und eine Datenbank, in der die Daten gespeichert werden. Ändert der Benutzer nun einen Eintrag in der TableView, so wird diese Änderung folglich auch im ArrayController getan. Aber nicht in der Datenbank... dh ich muss die "edit"-Events irgendwie abfangen und ebenfalls in die Datenbank schreiben, damit Inhalt des ArrayController + Inhalt der Datenbank übereinstimmen, sodass der Benutzer beim nächsten Start der Applikation keinen Schreck bekommt.
Soweit so gut...
NSTableView hat leider keine Delegate Methode, die mich über die Art und Weise der vorgenommenen Bearbeitung einer Zeile in NSTableView informiert. Ich habe lediglich eine entsprechende Methode gefunden, die NSTableView aufruft... tap tap... Subclassen ist angesagt...
"Abfangen" möchte ich:
- (BOOL)textShouldEndEditing:(NSText *)textObject
von NSTableView und als Delegate verfügbar machen. Ob das in Cocoa der richtige Weg ist - k/A...
Aber ich habe es mal gemacht:
Quellcode
- @implementation FileCardTableView
- - (BOOL)textShouldEndEditing:(NSText *)textObject {
- [self textShouldEndEditingDelegate:textObject];
- return YES;
- }
- - (BOOL)textShouldEndEditingDelegate:(NSText *)textObject {
- BOOL ok = YES;
- if([[self delegate] respondsToSelector:@selector(textShouldEndEditingDelegate:)]) {
- ok = [[self delegate] textShouldEndEditingDelegate:textObject];
- }
- return ok;
- }
- @end
Nun müsste ich in meinem TableViewDelegate ja mittels "textShouldEndEditingDelegate" über Editierversuche meines gelieben Benutzers doch informiert werden - und ja - es klappt...
In meinem TableViews Delegage habe ich folgende Funktion:
Diese gibt mir einen Zeige auf die momentan selektierte Karteikarte zurück. fileCardsController ist der NSArrayController mit den FileCard Objekten.
Ob das so ganz der richtige Weg ist - bin ich mir nicht sicher... aber seis drum...
In meinem TableView Delegate kann ich nun mit meinem eigenen Delegate die Editierversuche abfangen und versuchen in die Datenbank zu schreiben.
Gesagt getan.
Quellcode
- - (BOOL)textShouldEndEditingDelegate:(NSText *)textObject {
- FileCard *fileCard = [self selectedFileCard]; // aktuell selektierte karteikeite
- FileCardDAO *fileCardDAO = [[FileCardDAO alloc] init]; // mein data access object
- FileCard *dbFileCard = [fileCardDAO loadWithFileCardId:[fileCard fileCardId]]; // kopie der aktuellen Karteikarte aus DB holen
- [dbFileCard setFrontSide:[textObject string]]; // neuen Wert für ein member von FileCard
- [fileCardDAO updateWithFileCard:dbFileCard]; // Karteikarte wieder in DB schreiben (update)
- [fileCard setFrontSide:[textObject string]]; // ArrayController-Element updaten
- return YES;
- }
Und was geschieht beim editieren? Die Daten werden richtig in der Datenbank auf den neusten Stand gebracht aber in der Zelle, die bearbeitet steht nun plötzlich der Wert der Zelle über der bearbeiteten. (siehe 1. Screenshot)
Komisch dabei ist: Falls ich eine weniger dynamische Version meines Quelltextes verwende:
Quellcode
- - (BOOL)textShouldEndEditingDelegate:(NSText *)textObject {
- FileCard *fileCard = [self selectedFileCard]; // aktuell selektierte karteikeite
- FileCardDAO *fileCardDAO = [[FileCardDAO alloc] init]; // mein data access object
- FileCard *dbFileCard = [fileCardDAO loadWithFileCardId:[fileCard fileCardId]]; // kopie der aktuellen Karteikarte aus DB holen
- [dbFileCard setFrontSide:[textObject string]]; // neuen Wert für ein member von FileCard
- [fileCardDAO updateWithFileCard:dbFileCard]; // Karteikarte wieder in DB schreiben (update)
- [fileCard setFrontSide:@"FUCK"]; // ArrayController-Element updaten
- return YES;
- }
dann klappt es wunderbar, wie erwartet (siehe 2. Screenshot) Ich habe nur eine Zeile verändert.
[fileCard setFrontSide:[textObject string]];
wurde zu
[fileCard setFrontSide:@"FUCK"];
Was habe ich übersehen?
Der, der den Fehler findet bekommt 10 Euro
Die Objective-Cloud ist fertig wenn sie fertig ist. Beta heißt Beta.
Objective-C und Cocoa Band 2: Fortgeschrittene
Cocoa/Objective-C Seminare von [co coa:ding].
Objective-C und Cocoa Band 2: Fortgeschrittene
Cocoa/Objective-C Seminare von [co coa:ding].