Lernziel-C Tag 4

Willkommen zu Teil vier dieser Serie zu Objective-C. Bisher haben wir uns viel mit Theorie und den Grundsätzen und der Funktionalität der Sprache beschäftigt, um eine gute Vorstellung davon zu bekommen, wie sie funktioniert. Heute werden wir eine einfache Klasse erstellen, die dem in den vorherigen Teilen dieser Serie untersuchten Fahrzeugbeispiel ähnlich ist. Unsere Klasse nimmt die Details eines Autos auf, damit wir die Werte erhalten und festlegen können. Nach dem heutigen Beispiel sollten Sie in der Lage sein, Ihre eigenen Klassen in Xcode zu erstellen und mit ihnen herumzuspielen.

Bisher hatten wir einige großartige Rückmeldungen per E-Mail, Twitter und Kommentare. Es ist großartig zu sehen, dass sich so viele Leute für dieses Thema interessieren und es ist noch besser zu sehen, dass so viele von euch es selbst ausprobieren und einige großartige Fragen stellen. Mach weiter!

Fertig machen

Starten Sie, indem Sie Xcode starten und ein neues Projekt erstellen. Klicken Sie unter dem Mac OS X-Trennzeichen auf Anwendung und dann auf Befehlszeilenprogramm. Ändern Sie schließlich das Dropdown-Feld, um den Typ auf Foundation festzulegen.

Speichern Sie das Projekt wie immer Sie wollen, ich habe meine CarApp angerufen. Sobald das Projektfenster angezeigt wird, müssen wir eine neue Klasse erstellen. Drücken Sie Befehlstaste-N (oder Datei> Neue Datei), navigieren Sie unter Mac OS X zu Cocoa-Klasse und wählen Sie Objective-C-Klasse aus. Stellen Sie sicher, dass die Unterklasse von auf NSObject gesetzt ist, und klicken Sie auf Weiter. Benennen Sie Ihre Klasse SimpleCar, stellen Sie sicher, dass eine .h-Datei erstellt wird, und speichern Sie sie.

Unsere Klasse existiert jetzt, tut aber nichts. Ändern wir das, indem wir etwas Code geben. Denken Sie daran, dass wir in Objective-C unseren Code in zwei Teile aufteilen: Schnittstelle und Implementierung. Es ist logisch sinnvoll, zuerst an der Schnittstelle zu arbeiten, also beginnen wir hier.

Schnittstelle codieren

Öffnen Sie die Datei SimpleCar.h und in ihrem aktuellen Status sollte es so aussehen (ich habe den Kommentar-Header von unten weggelassen)

 #einführen  @ Schnittstelle SimpleCar: NSObject  @ End 

Als Erstes fügen wir Cocoa.h hinzu, wodurch wir Zugriff auf Dinge wie NSString, NSMutableString usw. erhalten. Anschließend erstellen wir unsere Klasse (SimpleCar) als Unterklasse von NSObject.

Nun müssen wir entscheiden, welche Informationen unsere Klasse speichern muss. Da wir ein Auto als Beispiel verwenden, müssen wir Informationen zum Auto speichern, z.

  • Machen
  • Modell
  • VIN

Es gibt noch viel mehr, auf die wir eingehen könnten, aber für den Moment reicht das. Für jede dieser Eigenschaften müssen wir sie in einer für diesen Datentyp geeigneten Variable speichern. Marke und Modell bestehen aus einer Reihe von Zeichen (z. B. Text, Zahl und möglicherweise Interpunktion). Daher ist es sinnvoll, eine Zeichenfolge zu verwenden. Die VIN (Vehicle Identification Number) ist nur eine Nummer, daher verwenden wir diese Nummer. Unser Code sieht jetzt so aus (Header fehlt):

 @Interface SimpleCar: NSObject NSString * make; NSString * -Modell; NSNumber * vin;  @Ende 

Wir haben zuvor gesagt, dass zum Abrufen oder Setzen von Daten von einer Klasse eine Methode verwendet werden sollte. Um die Variablen festzulegen, müssen wir Methoden hinzufügen. Dazu machen wir vier: Eine setzt die Marke, eine das Modell, eine die VIN und eine letzte Methode setzt sowohl die AND-Modelle (nur um zu zeigen, wie Sie mehrere Argumente verwenden)..

 @Interface SimpleCar: NSObject NSString * make; NSString * -Modell; NSNumber * vin;  // Methoden setzen - (void) setVin: (NSNumber *) newVin; - (void) setMake: (NSString *) newMake; - (void) setModel: (NSString *) setModel; // Convenience-Methode - (void) setMake: (NSString *) newMake undModel: (NSString *) newModel; @Ende 

Methoden werden nach der geschweiften Klammer und vor @end deklariert. Wenn Sie vor der Methode einen Bindestrich (Minuszeichen) setzen, teilen wir dem Compiler mit, dass wir eine Instanzmethode deklarieren werden. Eine Instanzmethode ist eine Methode, die in unserer Instanz ausgeführt wird. Umgekehrt bedeutet ein Pluszeichen, dass die aufgerufene Methode eine Klassenmethode ist, für die später keine einzelne Objektinstanz ausgeführt werden muss.

Unsere erste Methode gibt void zurück, heißt setVin und verwendet eine NSNumber als Argument. Unsere zweite Methode ist ähnlich, sie gibt void zurück, ist setMake und nimmt einen NSString als Argument. Der dritte ist derselbe mit einem anderen Namen.

Unsere letzte Methode gibt ebenfalls void zurück, nimmt jedoch zwei Parameter an: newMake und newModel, die beide NSString sein sollten. Die in dieser Methode verwendete Benennung ähnelt der Benennung der meisten Objective-C-Methoden: in reinem Englisch. Wenn Sie also die erlaubte Methode lesen, ist es offensichtlich, dass die Methode "Make and Model" setzt. Beachten Sie, dass der Methodenname in diesem Fall 'setMake: andModel:' lautet - alle Argumenttitel sind im Methodennamen enthalten.

Ein wichtiger Hinweis ist, dass wir (Void) verwenden, da unsere Methoden nichts zurückgeben müssen. Da sie lediglich Daten festlegen und nichts zurücksenden müssen (z. B. eine Erfolgsmeldung), verwenden wir einfach void.

Als Nächstes fügen wir die Methoden hinzu, die wir zum Abrufen der Werte verwenden werden. Obwohl wir unsere Methoden "get" und "set" -Methoden nennen, verwenden wir normalerweise nur "set" im Titel und lassen "get" weg. Wie Sie Ihre Methoden benennen, liegt letztlich bei Ihnen, aber das Ablegen von "Get" ist üblich und hilft, Verwirrung zu vermeiden.

Unsere neuen Methoden sehen folgendermaßen aus:

 // Methoden setzen - (void) setVin: (NSNumber *) newVin; - (void) setMake: (NSString *) newMake; - (void) setModel: (NSString *) newModel; // Convenience-Methode - (void) setMake: (NSString *) newMake undModel: (NSString *) newModel; // Methoden erhalten - (NSString *) make; - (NSString *) Modell; - (NSNumber *) vin; 

Beachten Sie, dass die get-Methoden dieselben Namen wie die Variablen in der Klasse verwenden. Dies macht es einfach, wenn wir die Variablen abrufen. Es ist, als würden wir direkt auf die Variablen zugreifen, wodurch die get-Methoden im Wesentlichen transparent erscheinen.

Kodierung der Implementierung

Nun, da die Schnittstelle vorhanden ist und wir wissen, was die Klasse tun wird, müssen wir unsere Methoden implementieren. Rückblickend haben wir vier Methoden, die wir implementieren müssen: setVin, setMake, setModel und setMake: andModel. Kopieren Sie die Methodendeklarationen in Ihre Zwischenablage (Cmd + C), bevor Sie Dateien verschieben. Schließen Sie nun SimpleCar.h und starten Sie SimpleCar.m im Editor. Die Methodendeklarationen werden zwischen @implementation und @end eingefügt.

 @implementation SimpleCar // Methoden setzen - (void) setVin: (NSNumber *) newVin; - (void) setMake: (NSString *) newMake; - (void) setModel: (NSString *) newModel; // Convenience-Methode - (void) setMake: (NSString *) newMake undModel: (NSString *) newModel; // Methoden erhalten - (NSString *) make; - (NSString *) Modell; - (NSNumber *) vin; @Ende 

Offensichtlich ist das nicht richtig, also müssen wir die Semikolons gegen geschweifte Klammern eintauschen, wo die inneren Abläufe der Methode so aussehen werden:

 @implementation SimpleCar // set Methods - (void) setVin: (NSNumber *) newVin  - (void) setMake: (NSString *) newMake  - (void) setModel: (NSString *) newModel  - (void) setMake: (NSString *) newMake undModel: (NSString *) newModel  // Methoden abrufen - (NSString *) make  - (NSString *) model  - (NSNumber *) vin  @end 

Nun müssen wir unseren Methoden etwas Code geben. Beginnen wir mit den Getter-Methoden, da sie einfach genug sind. Für jede Getter-Methode müssen wir nur sicherstellen, dass die Funktion das zurückgibt, was sie zurückgeben soll. Aus diesem Grund sehen unsere Getter-Methoden so aus:

 - (NSString *) make return make;  - (NSString *) model return model;  - (NSNumber *) vin return vin;  

Merken: Die Methoden geben die Variablen zurück, die wir in der Schnittstellendatei definiert haben. Lassen Sie sich nicht zwischen den Methodennamen und den Variablennamen verwechseln.

Das ist ziemlich einfach, wenn wir zum Beispiel make aufrufen, dann gibt make den Zeiger auf einen NSString zurück - in diesem Fall auf die make-Variable. Dasselbe gilt für model und vin (außer natürlich, dass vin eine Zahl zurückgibt).

Bei den Setter-Methoden sehen wir uns zuerst den Code an und gehen ihn anschließend durch. Unsere Setter-Methoden sehen so aus:

 // Methoden setzen - (void) setVin: (NSNumber *) newVin [vin release]; vin = [[NSNumber Alloc] init]; vin = newVin;  - (void) setMake: (NSString *) newMake [make release]; make = [[NSString zuteilen] initWithString: newMake];  - (void) setModel: (NSString *) newModel [Modellversion]; model = [[NSString-Zuordnung] initWithString: newModel];  // Convenience-Methode - (void) setMake: (NSString *) newMake undModel: (NSString *) newModel // Verwenden Sie unsere Methoden früher [self setMake: newMake]; [self setModel: newModel];  

Die Set-Methoden sind etwas komplizierter als unsere Get-Methoden. Wir möchten die Werte, die an jede Methode übergeben werden, so zuordnen, dass sie der Klasse gehören. Wir geben diese Variablen zuerst frei, falls sie bereits vergeben sind. Wenn sie nicht zugewiesen sind, sind sie null und keine Objekte ignorieren Nachrichten, die an sie weitergeleitet werden. Wir werden diese Fragen ausführlicher behandeln, wenn wir das Speichermanagement diskutieren.

Da wir tatsächlich Speicher für unsere Objekte in den Setter-Methoden zugewiesen haben, müssen wir sicherstellen, dass wir sie freigeben, wenn das Objekt aus dem Speicher freigegeben wird. Dazu müssen wir eine benutzerdefinierte Dealloc-Methode hinzufügen:

 -(void) dealloc [vin release]; [Freigabe machen]; [Model Release]; [Super Dealloc];  

Die Klasse testen

Herzliche Glückwünsche! Wenn Sie alles oben befolgt haben, sollten Sie jetzt eine Arbeiterklasse haben (wenn nicht, laden Sie die in diesem Artikel verfügbaren Quelldateien herunter). Also, lasst es uns testen.

Öffnen Sie die Hauptdatei Ihres Projekts (meine heißt CarApp.m), die standardmäßig so aussehen soll:

 #einführen  int main (int argc, const char * argv []) NSAutoreleasePool * pool = [[NSAutoreleasePool Allocation] init]; // Benutzerdefinierten Code hier einfügen ... NSLog (@ "Hello, World!"); [pool drain]; 0 zurückgeben;  

Löschen Sie den Kommentar und die NSLog-Zeile, da wir sie jetzt nicht benötigen.

Um unsere Klasse verwenden zu können, müssen wir sie in das Programm aufnehmen. Fügen Sie unter der ursprünglichen Importzeile die folgende Zeile hinzu:

 #import "SimpleCar.h" 

Unsere Klasse steht jetzt zur Verfügung, aber wir müssen eine Instanz davon erstellen, um sie testen zu können. Hier ist der Code, der insgesamt verwendet wird:

 #einführen  #import "SimpleCar.h" int main (int argc, const char * argv []) NSAutoreleasePool * pool = [[NSAutoreleasePool Allocation] init]; SimpleCar * myCar = [[SimpleCar-Zuordnung] init]; NSNumber * newVin = [NSNumber numberWithInt: 123]; [myCar setVin: newVin]; [myCar setMake: @ "Honda" undModel: @ "Civic"]; NSLog (@ "Das Auto ist:% @% @", [myCar make], [myCar-Modell]); NSLog (@ "The vin is:% @", [myCar vin]); [myCar release]; [pool drain]; 0 zurückgeben;  

Zunächst erstellen wir einen Zeiger auf eine Instanz von SimpleCar mit dem Namen myCar. Als nächstes verwenden wir "old "und" init "- diese werden später besprochen.

Da wir nun eine NSNumber an die setVin-Methode übergeben müssen, erstellen wir hier eine. Wieder erzeugen wir einen Zeiger auf eine NSNumber-Instanz namens newVin und initiieren ihn mit dem ganzzahligen Wert von 123. Die Konstante '123' ist eine ganze Zahl, weshalb wir numberWithInt verwenden.

Als Nächstes rufen wir unsere Methoden auf. Zuerst legen wir fest, wer die Nachricht erhalten soll (myCar), und verwenden dann die Methode setVin. Nach dem Doppelpunkt ist der Wert, den wir der Methode liefern, die die zuvor erstellte NSNumber ist. Als Nächstes machen wir dasselbe, rufen aber die setMake-Methode mit zwei Parametern auf. Vor diesen Parametern wird ein @ -Zeichen vorangestellt, um dem Compiler mitzuteilen, dass Folgendes ein String ist.

Schließlich veröffentlichen wir myCar, sobald wir damit fertig sind - dazu später mehr in der Reihe unter Speicherverwaltung.

Unsere Klasse funktioniert jetzt. Um den Beweis zu sehen, haben wir einige NSLog-Anweisungen hinzugefügt, um die Werte auf der Konsole zu drucken. Wenn Sie die Konsole öffnen (Ausführen> Konsole) und dann Ihre App erstellen und ausführen, sollten Sie eine Ausgabe ähnlich der folgenden sehen:

Eigentum und Synthesize

Wenn Sie sich den Code oben ansehen, erscheint eine Menge recht sinnlos und übertrieben. In unseren Getter-Methoden geben wir beispielsweise lediglich eine Instanzvariable zurück. Dies erfordert jedoch drei Zeilen Code, um etwas einfaches zu tun. In unseren Setter-Methoden setzen wir lediglich Instanzvariablen - im Wesentlichen alle unsere Methoden, mit Ausnahme unserer Methode, die zwei Argumente akzeptiert, wirken aufgebläht und stehen im Weg. Objective-C löst dies mit @property und @synthesize, die unsere Accessor-Methoden ersetzen und für eine viel bessere Codierung sorgen.

So sieht unsere neue Interface-Datei mit Eigenschaften aus:

 #einführen  @Interface SimpleCar: NSObject NSString * make; NSString * -Modell; NSNumber * vin;  @property (readwrite, keep) NSString * make; @property (Readwrite, Retain) NSString * -Modell; @ property (readwrite, keep) NSNumber * vin; // Convenience-Methode - (void) setMake: (NSString *) newMake undModel: (NSString *) newModel; @Ende 

Wow, das ist wirklich viel kürzer. Was passiert also mit den @property-Deklarationen? Zuerst sagen wir dem Compiler, dass wir eine Eigenschaft mit @property deklarieren, dann folgen Attribute für diese Eigenschaft. Die Attribute sind der Lese- / Schreibstatus einer Eigenschaft und einige Speicherverwaltung. Wir haben readwrite für alle verwendet, was bedeutet, dass Getter- und Setter-Methoden dynamisch für unsere Instanzvariablen erstellt werden (wir könnten writeonly oder readonly nur für die eine oder die andere verwenden). Der Grund, aus dem wir keep verwenden, wird beim nächsten Mal klar, wenn wir die Speicherverwaltung behandeln.

Bevor dies funktionieren kann, müssen wir es in unsere Implementierungsdatei implementieren. Dazu verwenden wir @synthesize. Unsere neue Implementierungsdatei sieht folgendermaßen aus:

 #import "SimpleCar.h" @implementation SimpleCar @synthesize make, model, vin; - (void) setMake: (NSString *) newMake undModel: (NSString *) newModel [self setMake: newMake]; [self setModel: newModel];  @Ende 

Sieht das nicht besser aus? Stellen Sie sich das so vor: @property ersetzt alle Interface-Methodendeklarationen für Getter und Setter und @synthesize ersetzt die eigentlichen Methoden selbst. Die Getter und Setter werden jetzt dynamisch erstellt, und wir müssen keine Zeit damit verschwenden, sie zu erstellen, es sei denn, wir müssen etwas wirklich Besonderes tun.

Einpacken

Sie sollten jetzt Klassen, Objekte und Instanzen fest im Griff haben. Sicher, Sie erstellen keine Klassen, die die Welt noch verändern werden, aber dieses Zeug braucht Zeit. Es ist besser, durch Beispiele zu lernen. Wenn Sie also nicht während des Programmiervorgangs codieren, sollten Sie mindestens die Quelldateien herunterladen und lesen (und kompilieren), um sicherzustellen, dass Sie 100% ig auf dem Laufenden sind.

Nächstes Mal

In diesem Lernprogramm haben wir viel über das Speichermanagement gesprochen. Es ist ein sehr wichtiges Thema, das angesprochen werden muss (Wortspiel beabsichtigt). Deshalb werden wir beim nächsten Mal darauf eingehen. Es ist zwar nicht das lustigste Thema oder das einfachste, mit dem man sich auseinandersetzen kann, aber es ist absolut entscheidend, wenn man ein erfahrener Objective-C-Programmierer werden möchte.

Herausforderung

Die Herausforderung dieser Woche mag etwas schwierig sein, aber wir werden sehen, wie es Ihnen geht. Wenn Sie nicht den gesamten Code oben kopiert haben, laden Sie zunächst die in diesem Artikel enthaltenen Quelldateien herunter. Die Herausforderung besteht darin, dem Projekt eine weitere Klasse hinzuzufügen. Diesmal sollte es sich jedoch um eine Unterklasse von SimpleCar handeln (denken Sie daran, wir definieren die übergeordnete Klasse in der Schnittstellendatei). Wenn dies möglich ist, spielen Sie herum und verwenden Sie die vererbten Methoden. Versuchen Sie, eigene Methoden hinzuzufügen, wie z. B. Motorgröße, Türen oder Höhe.

Merken: Wenn Sie Fragen oder Fragen haben, schreiben Sie einen Kommentar oder schreiben Sie mir eine Nachricht auf Twitter. Die einzige dumme Frage ist die, die Sie nicht gestellt haben - diese Serie beschäftigt sich mit dem Lernen, also fragen Sie einfach weiter!