Programmieren mit Swift - Für macOS und iOS
Programmieren mit Swift - Für macOS und iOS
NSCoding Protokol

Den erstellten Character zu speichern ist keine schwierige Aufgabe, wenn man sich der von Apple mitgelieferten Archivierungslösungen bedient. Dabei kommt ein Verfahren zur Anwendung, das in der Datenverarbeitung auch als Serialisierung bekannt ist. Bei der Serialisierung wird der aktuelle Zustand eines Objektes gespeichert und kann zu einem späteren Zeitpunkt wiederhergestellt werden. Gelegentlich nennt man diesen Vorgang auch archivieren.
Der erste Schritt, um ein Objekt zu serialisieren, besteht darin, die Klasse so zu erweitern, dass sie archiviert werden kann. Dazu ändern Sie zunächst in der Character.h Datei die Zeile
@interface Character : NSObject {
in
@interface Character : NSObject <NSCoding> {
Mit dieser zusätzlichen Anweisung haben Sie der Klasse ein Protokoll, in diesem Fall NSCoding, hinzugefügt. Protokolle entsprechen in etwa den Interfaces, die Sie vielleicht aus anderen Programmiersprachen kennen. Sie werden Ihre Anwendung jetzt auch nicht mehr erfolgreich kompilieren können, denn mit dieser Deklaration haben Sie sich verpflichtet, auch die für NSCoding notwendigen Methoden zu implementieren. Das ist bisher aber nicht geschehen und der Compiler merkt das.
Das NSCoding-Protokoll ist dabei recht pflegeleicht, denn es verlangt nur nach zwei Methoden. Eine Methode, um die Klasse zu codieren, und eine Methode, um die Klasse aus codierten Daten zu initialisieren. Dadurch werden die Informationen zwar weder gespeichert noch geladen, aber sie werden in die richtige Form gebracht. Einfach ausgedrückt erfährt die Klasse, wie sie ihre Daten speichern kann.

Bei der Implementierung sollten Sie darauf achten, die Methoden mit den richtigen Namen zu versehen. Eine kleine Abweichung genügt und die Klasse entspricht nicht dem Protokoll. Dafür genügt es aber auch, die Methoden nur in der Character.m Datei umzusetzen. Eine Definition in der Headerdatei ist nicht nötig.

Ohne Anweisungen sehen die Methoden so aus. Die Code-Sense Hilfe kann Ihnen bei der Eingabe eine große Hilfe sein, da sie die passenden Methoden vorschlägt.
- (void) encodeWithCoder:(NSCoder *)aCoder
{
}
- (id) initWithCoder:(NSCoder *)aDecoder
{
}
Kümmern wir uns zunächst um encodeWithCoder. In dieser Methode sollen alle Instanzvariablen so umgewandelt werden, dass sie auf einen Datenträger geschrieben werden können. Der als Parameter mitzugebende NSCoder erledigt das später. Da in der Klasse Character nur Objekt-Typen zum Einsatz kommen, sind die für die Codierung nötigen Anweisungen alle ähnlich.
- (void) encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:[
self strength] forKey:@"strength"];
    [aCoder encodeObject:[self dexterity] forKey:@"dexterity"];
    [aCoder encodeObject:[self constitution] forKey:@"constitution"];
    [aCoder encodeObject:[self intelligence] forKey:@"intelligence"];
    [aCoder encodeObject:[self wisdom] forKey:@"wisdom"];
    [aCoder encodeObject:[self charisma] forKey:@"charisma"];
    [aCoder encodeObject:[self characterName] forKey:@"characterName"];
    [aCoder encodeObject:[self race] forKey:@"race"];
    [aCoder encodeObject:[self charClass] forKey:@"charClass"];
    [aCoder encodeObject:[self image] forKey:@"image"];
}
Ausser encodeObject gibt es auch für andere Datentypen Anweisungen wie encodeFloat oder encodeBool. Die werden hier aber nicht gebraucht. Der verwendete Key muss nicht dem Variablenbezeichner entsprechen, er wird nur dann wichtig, wenn man die Daten wieder einliest und den einzelnen Variablen zuordnen will. Sie können den Keys einen beliebige Namen geben, solange Sie konsequent sind und diesen auch in der initWithCoder-Methode benutzen.

Es ist die Aufgabe von initWithCoder, aus geladenen Daten wieder ein Objekt mit Instanzvariablen und Werten dieser Klasse zu machen. Da es sich um eine Inititalisierung handelt, muss auch erst wieder die Superklasse initialisiert werden.
- (id) initWithCoder:(NSCoder *)aDecoder
{
    if(![super init])
        return nil;

    [self setStrength:[aDecoder decodeObjectForKey:@"strength"]];
    [self setDexterity:[aDecoder decodeObjectForKey:@"dexterity"]];
    [self setConstitution:[aDecoder decodeObjectForKey:@"constitution"]];
    [self setIntelligence:[aDecoder decodeObjectForKey:@"intelligence"]];
    [self setWisdom:[aDecoder decodeObjectForKey:@"wisdom"]];
    [self setCharisma:[aDecoder decodeObjectForKey:@"charisma"]];
    [self setCharacterName:[aDecoder decodeObjectForKey:@"characterName"]];
    [self setRace:[aDecoder decodeObjectForKey:@"race"]];
    [self setCharClass:[aDecoder decodeObjectForKey:@"charClass"]];
    [self setImage:[aDecoder decodeObjectForKey:@"image"]];

    return self;
}
Damit sind die Arbeiten am Quellcode der Klasse Character abgeschlossen. Um die Daten aber letztendlich auf die Festplatte zu bekommen, sind noch einige Schritte mehr nötig.

nächste Seite