NSTableView - NSMutableDictionary Problem

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • NSTableView - NSMutableDictionary Problem

    Ich habe mir ein kleines Programm geschrieben,
    was in eine NSTableView und NSDictionary Datens‰tze schreiben soll, die abspeichern und wieder laden soll.
    Nun hab ich 2 Probleme.
    1. Wenn ich einen neuen Datensatz einf¸ge, dann wird dieser erst sichtbar, wenn ich die einzelnen Spalten mit der Maus einmal angeklickt habe.
    2. Ich bekomme keinen zweiten Datensatz in die NSDictionary.
    Immer wenn ich einen neuen einf¸gen mˆchte, dann wird der erste ¸berschrieben :-(

    Ich habe das ganze aus einem Tutorial, wo direkt 15 Datens‰tze in die Table geschrieben werden, die dann ge‰ndert, abgespeichert und geladen werden kˆnnen.
    Ich mˆchte das aber mit beliebigen hinbekommen.

    Code zum einf¸gen:

    Quellcode

    1. - (void)setmyrecord:(NSMutableArray *)newmyrecord {
    2. [newmyrecord retain];
    3. [myrecord autorelease];
    4. myrecord = newmyrecord;
    5. }
    6. - (NSMutableArray *)genNeuerSatz {
    7. NSMutableArray *array = [NSMutableArray array];
    8. Myrecord *rec = [[Myrecord alloc] init];
    9. [rec setName: @"hier Name"];
    10. [rec setTelefon: @"hier Telefon"];
    11. [array addObject: rec];
    12. [rec release];
    13. return array;
    14. }
    15. - (IBAction)neuersatz:(id)sender
    16. {
    17. [self setmyrecord:[self genNeuerSatz ]];
    18. }
    Alles anzeigen


    Werde euch dann denm‰chst ˆfterst mir solch banalen Fragen nerven :-) Sorry, nach ¸ber 6 Jahren Delphi, ist Cocoa doch wieder etwas ganz neues.

    Grufl Sven
    :wq! /dev/null
  • RE: NSTableView - NSMutableDictionary Problem

    Zuerst zu Punkt 2.:

    Wenn ich das Programmlisting richtig interpretiere, mˆchtest du mit der Methode setmyrecord: einen neuen Datensatz, mit den initialisierten Daten aus der Methode genNeuerSatz, hinzuf¸gen.
    Mit [myrecord autorelease] werden aber die alten Daten weggeworfen und im nachfolgenden Befehl durch newmyrecord ersetzt. Hier sollte eigentlich eine Methode mit 'append...', 'add...' oder 'insertRecord:..atIndex:...' stehen, oder?

    Also besser in der Methode neuerSatz: (oder neuerSatzAnfuegen:)
    [myrecord append: [self genNeuerSatz]];

    die setmyrecord: Methode dient dann dazu, die Daten zu ersetzen und nicht dazu sie anzuf¸gen (wie wohl urspr¸nglich auch so gedacht).

    Nebenbei, es empfiehlt sich die Grofl- und Kleinschreibregeln einzuhalten, das macht es f¸r andere (und einen selbst) einfacher, Programmbeispiele zu lesen.

    Zu Punkt 1.:
    Ich vermute, du muflt dem NSTableView auch bekannt machen,
    dass ein neuer Datensatz hinzugef¸gt bzw. ge‰ndert wurde.
    Etwa mit:
    [myTableView reloadData] oder [myTableView noteNumberOfRowsChanged].

    Ich hoffe, das hilft weiter.
  • danke, das mit der Tabelle hat wunderbar funktioniert.
    Aber das mit dem Append nicht.

    Sowie ich den Code verstehe :-)!
    wird in der Funktion genNeuerSatz, erst alles in einen NSMutableDictionary (rect) geschrieben, was abgeleitet ist von Myrecord. Das wird in einen Array ¸bergeben und dieser dann durch den R¸ckgabewert in der Funktion setmyrecord in das NSMutableDictionary geschrieben

    Quellcode

    1. @interface Myrecord : NSObject <NSCoding> {
    2. NSString *name;
    3. NSString *telefon;
    4. }


    Wenn ich auf myrecord oder Myrecord das append anwendee bekomme ich eine Fehlermeldung das NsMutablearry (myrecord) nicht darauf reagiert bzw das bei Myrecord die Meldung selector not recognized

    Sven
    :wq! /dev/null
  • du hast es auch mit [meinArray addObject:objekt] probiert, oder? die methode heiflt nichts mit append, sondern addObject.

    ich weifl ja nicht, wie der rest deines cods aussieht, aber es ist auch immer hilfreich nach dem einf¸gen/‰ndern deiner daten, ein [myTable reloadData] zu schicken, damit zwingst du die tabelle, ihre daten neu zu laden. speziell dann sinnvoll, wenn am ende neue objekte hinzugef¸gt wurden; woher sonst sollte die tabelle wissen, dafl sie auf einmal mehr daten anzeigen soll?
    if (!exit(-1)) fprintf(stderr, "exit call failed. Program will continue\n");
  • So wie Myrecord bei dir definiert ist, ist es eine Unterklasse von NSObject und nicht NSMutableDictionary. NSMutableDictionary taucht bei deinen Beispielen nie auf.

    Soweit erkennbar willst du eine Liste mit Namen und dazugehˆrigen Telefonnummern, die von einem NSTableView dargestellt werden sollen.

    Um die Liste zu f¸hren reicht ein NSMutableArray, das lauter Objekte deiner Klasse Myrecord (besser MyRecord) enth‰lt.
    Dieses Array wird normalerweise von dem 'Controller Objekt', das die Benutzeroberfl‰che mit dem Datenmodell verbindet, verwaltet.

    Um einen neuen Eintrag zu generieren, erzeugst du einfach ein myRecord Objekt (mittels dem alloc-init-Schema oder als
    Klassenmethode).
    Hier beispielsweise die Klassenmethode:

    + (MyRecord *) defaultMyRecord {
    MyRecord *newRecord = [[MyRecord alloc] init];
    // setzen der default Werte hier
    [newRecord autorelease]; //
    return newRecord;
    }

    Den Eintrag kannst Du dann direkt an das NSMutableArray
    durchreichen:

    Mit dem Controller

    @interface MyController: NSObject {
    NSMutableArray *myRecordList;
    IBOutlet NSTableView *myTableView;
    // weitere Objekte und IBOutlets hier
    }

    reicht als IBAction zum Anh‰ngen eines neuen Eintrags:

    - (IBAction) neuerEintrag {
    [myRecordList addObject:[MyRecord defaultMyRecord]];
    [myTableView reloadData];
    }
  • RE: NSTableView - NSMutableDictionary Problem

    Original von Stalkingwolf

    ...

    Quellcode

    1. - (void)setmyrecord:(NSMutableArray *)newmyrecord {
    2. [newmyrecord retain];
    3. [myrecord autorelease];
    4. myrecord = newmyrecord;
    5. }


    ...

    Grufl Sven


    Vielleicht noch eine kleine Bemerkung:

    Memberroutinen, die mit "set*" beginnen, sing eigentlich f¸r das Key-Value Coding reserviert. Wenn man sich diese Mˆglichkeit nicht verbauen will, sollte man sie nur bei den Zugriffsmethoden auf die Membervariablen einsetzen.

    Das Schema ist sehr einfach, wenn man sich an die Konventionen h‰lt (member Variable beginnen IMMER mit einen kleinen Buchstaben!)

    Beispiel:

    NSString *myVariable;

    Dann:

    - (NSString *) myVariable { return myVariable; }

    Und:

    - (void) setMyVariable: (NSString *) neuerWert
    {
    if ( neuerWert != myVariable )
    { id alterWert = myVariable;

    myVariable = [neuerWert retain];
    [alterWert release];
    }
    }

    Der Getter ist also gleich dem Variablennamen und die Setter-Methode setzt ein set davor und wandelt den ersten Buchstaben in einen Groflbuchstaben um.

    Key-Value-Coding durchzieht Cocoa wir ein roter Faden, auch wenn man es am Anfang nicht versteht und noch andere Probleme hat, man sollte sich dennoch an die Konvention halten und Zugriff auf die Members AUSSCHLIESSLICH durch Methoden realisieren und dabei auch noch obige Namenskonvention einhalten.
    Es gibt genau 10 Sorten von Menschen.
    Die eine kennt das binaere Zahlensystem, die andere nicht.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von mac_held ()

  • Ein sehr guter Artikel, zu den Namenskonventionen bei Objective-C (Englisch):

    stepwise.com/Articles/Technical/2002-10-13.01.html

    Zusammengefaflt:

    - Klassen, C-Funktionen, Strukturen und Konstanten beginnen mit einem Groflbuchstaben.

    vorzugsweisen verwendet man zwei oder Groflbuchstaben als "persˆnliches" oder Firmenk¸rzel, um Namenskonflikten zu entgehen (z.B. "NS", "OF", etc.)

    - methoden und variablen beginnen mit Kleinbuchstaben, z.B. - (id) objectForKey: (id) key;

    - Instanz variablen beginnen mit einem Unterstrich '_', z.B. _name

    mufl man nicht unbedingt einhalten, macht es einem aber selber auch schwerer *nicht* die accessor methoden zu nehmen. Einfach nur name ein zutippen ist leicht aber wenn man ¸ber _name nachdenken mufl f‰llt einem vielleicht ein auch lieber [self name] zu schreiben.

    - Accessor methoden (haben Kleinbuchstaben, s.o.) und entsprechen der Instanz Variable oder beginnen mit 'get' oder 'set' gefolgt von einem Groflbuchstaben.

    z.B.

    - (NSString *) name;
    - (NSString *) getName;
    - (void) setName: (NSString *)value;

    diese Schreibweise ist sehr wichtig (einschliefllich Grofl/Kleinschreibung) weil sonst Key-Value-Coding zerbricht. Was ist KVC?

    man kann _jedem_ Objekt einfach ein -valueForKey: @"name" schicken und die Objective-C Runtime wird versuchen:

    - zuerst die methode -name; auszuwerten
    - dann -getName;
    - dann sucht er nach einer instanzvariable namens name
    - dann nach _name

    den ersten wert, den die Runtime findet wird sie zur¸ckgeben.

    analog f¸r takeValue:forKey:

    macht vieles einfacher, z.B. kann man sich in der TableView Datasource viele if...else if... Konstrukte sparen:

    - (id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)tc row:(int)row {
    NSString *identifier = [tc identifier];
    id *entry = [[self array] objectAtIndex: row];

    return [entry objectForKey: identifier];
    }


    Wenn man jetzt das Object Entry ‰ndert, dann mufl man nur die Tabellen Spalten und Identifier im IB ‰ndern, ohne den Code anpassen zu m¸ssen...

    :-)

    Hoffe das hilft.
    - Titan =)

    "In theory, there is no difference between theory and practice.
    But in practice, there is."
    - Jan L.A. van de Snepscheut

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Titan ()

  • Jungs, danke ich habe alles hinbekommen.
    Ich habe das Programm nochmals neu geschrieben und greife nur auf einem NSMutableArray zu.
    Kann nun adden,deleten,editieren, navigieren, das ganze speichern und wieder laden.

    Vielen dank f¸r die ausf¸hrlichen Postings!

    Grufl Sven
    :wq! /dev/null