Objective-C

kurz & gut

Lars Schulten

Kapitel no. Einführung

Objective-C ist die Programmiersprache der letzten Jahre. Die Beliebtheit von Apples Plattformen, iOS und Mac OS X, sorgt dafür, dass die Sprache heute aktueller ist als je zuvor. Objective-C – kurz & gut ist ein kompaktes Handbuch zur Programmiersprache Objective-C. Es illustriert die grundlegenden Aspekte der Sprache mit kurzen Erklärungen, die von kleineren Beispielen aufgelockert werden, und bietet einen Überblick über die wichtigsten Technologien, Klassen, Nachrichten und Funktionen. Es richtet sich an alle, die bereits für andere Plattformen programmiert haben und sich nun in diese spannende Sprache einarbeiten wollen.

Anmerkung

Sie sollten mit mindestens einer Sprache vertraut sein, die eine C-artige Syntax nutzt. Objective-C setzt auf C auf und nutzt viele Elemente seiner Syntax unverändert. Das heißt, elementare Syntaxformen, wie Schleifen und Bedingungsanweisungen, sowie die elementaren C-Datentypen werden in diesem Buch nicht erläutert. Das bedeutet aber nicht, dass Sie C selbst beherrschen müssen. Eine beliebige an C angelehnte Programmiersprache mit äquivalenten Sprachelementen, Java oder C# beispielsweise, reicht vollkommen aus. Wenn Sie bislang nur mit dynamisch typisierten Sprachen wie z. B. JavaScript gearbeitet haben, sollten Sie sich allerdings unbedingt mit statischen Typsystemen vertraut machen.

Objective-C

Objective-C ist ein C-Dialekt. Es bildet eine vollständige Obermenge zu C und bietet alles, was auch C bietet. Es besitzt die gleichen Syntaxstrukturen und -elemente, nutzt die gleichen Datentypen und kann sogar auf die gleichen Bibliotheken zugreifen. Wenn Sie sich Objective-C von C her nähern, werden Ihnen also viele Dinge bekannt vorkommen. Sie könnten einem Objective-C-Compiler sogar Ihren alten C-Quellcode vorsetzen, und dieser würde ihn anstandslos kompilieren.

Haben Sie keine Erfahrung mit C, müssen Sie sich zusätzlich zum eigentlichen Objective-C-Kern noch mit gewissen Aspekten von C auseinandersetzen, die bei der Arbeit mit Objective-C unumgänglich sind. Auf einige dieser Aspekte wie C-Zeiger werden wir (kurz) eingehen, da ansonsten ein Verständnis von Objective-C unmöglich ist. Andere wie die diversen C-Datentypen und C-Syntaxstrukturen werden wir hier nicht beschreiben, da wir davon ausgehen, dass Sie bereits mit Sprachen wie Java, C# usw. gearbeitet haben, die ähnliche Features bieten. Sollte das nicht der Fall sein, müssen Sie die entsprechenden Informationen in einem geeigneten C-Buch nachschlagen.

Objective-C ist aber auch eine objektorientierte Programmiersprache, die alle Features bietet, die Ihnen aus anderen objektorientierten Programmiersprachen vertraut sein sollten: Objekte, Klassen, Schnittstellen, Vererbung, Polymorphie usw. Dazu erweitert es C um die entsprechenden Strukturen und Syntaxformen: Compilerdirektiven, Syntaxstrukturen zur Definition von Klassen und ihren Elementen, Syntaxstrukturen zur Arbeit mit Klassen und ihren Elementen und einige neue Datentypen. Das Buch erläutert die wichtigsten Aspekte der objektorientierten Programmierung und ihre spezifische Implementierung in Objective-C und geht dabei auch explizit auf die Punkte ein, an denen sich die objektorientierte Programmierung unter Objective-C von der in z. B. Java unterscheidet.

Werkzeuge und Plattformen

Objective-C ist eigentlich plattformunabhängig. Es gibt eine Reihe von Compilern, die Objective-C-Code kompilieren können, und verschiedene Laufzeitumgebungen, die in Objective-C-Code eingebunden werden können. In diesem Buch werden wir uns auf die Werkzeuge und die Laufzeitumgebung für Apples Plattformen konzentrieren. Einen kurzen Überblick über andere verfügbare Werkzeuge und Bibliotheken finden Sie in Kapitel 18, Alternative Plattformen. Da Apple die Sprache in den letzten Jahren umfassend erweitert hat, kann es sein, dass diese die neuesten Sprach-Features nicht immer vollständig unterstützen.

Anmerkung

Wir werden hier Objective-C in der Version behandeln, in der es von den Werkzeug- und Betriebssystemversionen unterstützt wird, die aktuell waren, als dieses Buch geschrieben wurde: XCode 4.6 mit Clang 4.2 und LLVM 3.2 sowie Mac OS X 10.8 und iOS 6. Das heißt auch, dass als Entwicklungsplattform ein System erforderlich ist, auf dem mindestens OS X 10.7 (Lion) läuft, da die benötigten Versionen von Xcode und Clang für frühere Betriebssystemversionen nicht verfügbar sind.

Die Beispiele

Die Beispiele sind eher knapp und nicht vollständig. In der Regel dienen sie nur der Illustration eines einzigen Problems und sind deshalb so einfach wie möglich gehalten. Sie machen extensiven Gebrauch von den neuesten Objective-C-Technologien und gehen, soweit nicht anders vermerkt, davon aus, dass der Code mit ARC-Unterstützung kompiliert wird.

Kapitel 2. Grundlagen

Objective-C bildet eine vollständige Obermenge zu C. Es nutzt nicht nur die gleichen elementaren Syntaxstrukturen, Datentypen und Schlüsselwörter wie C, sondern die Programmierung in Objective-C weist auch die gleichen Grundstrukturen wie die Programmierung in C auf.

Ein erstes Beispiel

Ein primitives Objective-C-Programm sieht fast genau so aus wie ein äquivalentes C-Programm und weist nur unerhebliche Unterschiede zu einem äquivalenten Java- oder C#-Programm auf:

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSLog(@"Die Welt ist alles, was der Fall ist!");
    }
    return 0;
}

Folgende Elemente sollten Sie aus C oder einer von C abgeleiteten Sprache kennen:

Die main()-Funktion dient als »Einsprungpunkt«. Die Ausführung jedes Objective-C-Programms beginnt mit dieser Funktion. Beachten Sie, dass main() eine klassische Funktion ist, keine Methode wie in Java oder C#.

Die Elemente, mit denen der Code operiert (Funktionen, Variablen usw.), haben stets einen Typ (int main(), int argc usw.).

Anweisungsblöcke stehen in geschweiften Klammern.

Anweisungen werden mit einem Semikolon abgeschlossen.

Unbekannt könnten Ihnen die #import-, @autorealesepool- und @"…"-Konstruktionen sein, da das Objective-C-eigene Syntaxelemente sind:

#import ist eine Objective-C-spezifische Präprozessordirektive, die eine Headerdatei importiert.

@autoreleasepool ist eine Objective-C-Compilerdirektive.

@"…" definiert ein Objective-C-Stringliteral.

Die beiden @-Formen werden in Kapitel 3, ausführlicher erläutert, #import im Abschnitt „Headerdateien“.

NSLog() ist eine Protokollierungsfunktion, die Nachrichten mit einem Zeitstempel versehen auf der Konsole ausgibt. Als erstes Argument erwartet sie ein Objective-C-Stringliteral. Das Stringliteral kann Formatangaben enthalten, die durch die nachfolgenden Argumente ersetzt werden, zum Beispiel:

NSLog(@"Das Leben ist %@", 1 > 0 ? @"schön" : @"be…");

Die Formatangabe %@ formatiert ein Objective-C-Objekt, hier das Objective-C-Stringobjekt, zu dem der Bedingungsausdruck ausgewertet wird. Daneben unterstützt Objective-C die von der printf-Spezifikation definierten Formatzeichen.

Code schreiben und kompilieren

Unter Mac OS X haben Sie zwei Möglichkeiten, Objective-C-Code zu schreiben und zu erstellen. Sie können beides mit Apples IDE Xcode tun, oder Sie schreiben mit einem Programm Ihrer Wahl und erstellen mit Apples Kommandozeilenwerkzeugen.

Xcode erhalten Sie im Mac App Store oder auf Apples Entwicklerseiten unter https://developer.apple.com/downloads/. Die Kommandozeilenwerkzeuge können Sie aus Xcode (unter Preferences…/Downloads/Components/Command Line Tools) installieren oder separat von Apples Entwicklerseiten für Ihr System herunterladen. Beachten Sie, dass Downloads und viele andere Ressourcen nur Mitgliedern in Apples Entwicklerprogramm zugänglich sind. Eine kostenlose Mitgliedschaft genügt.

Xcode

Der Code in diesem Beispiel ist eine nur minimal angepasste Fassung des Inhalts der main.m-Datei, die die Xcode-Projektvorlage für ein Kommandozeilenprojekt generiert. Sie können diesen Code kompilieren und ausführen, indem Sie in Xcode ein neues Kommandozeilenprojekt anlegen (File/New/Project/OS X/Application/Command Line Tool), dann nach Belieben vor dem Ausführen links im Projektnavigator main.m anwählen und im Editor die Änderungen vornehmen. Oder Sie klicken gleich auf den Run-Button, den Sie in Abbildung Abbildung 2.1 oben links sehen, um die Kompilation und Ausführung des Programms anzustoßen.

Abbildung 2.1 Apples IDE, Xcode

Kommandozeilenkompilation

Alternativ können Sie die Datei über die Kommandozeile kompilieren und ausführen. Geben Sie den Code in einen Texteditor Ihrer Wahl ein und speichern Sie die Datei unter einem Namen, der die Dateinamenserweiterung .m trägt, z.B. welt.m. Das ist die übliche Dateinamenserweiterung für Objective-C-Dateien. Öffnen Sie die Terminalanwendung und navigieren Sie in das Verzeichnis, in dem Sie Ihre Datei gespeichert haben. Geben Sie dann den folgenden Befehl ein (vorausgesetzt, Sie haben den gleichen Namen gewählt wie wir), um den Code zu kompilieren:

clang -fobjc-arc -framework Foundation -o Welt welt.m

clang ist Apples »Objective-C-Compiler«. Der Kommandozeilenschalter -fobjc-arc fordert Automatic Reference Counting (siehe Kapitel 11) an, -framework gibt die Frameworks an, gegen die gelinkt werden soll, -o den Namen der Ausgabedatei. Das Kompilat können Sie einfach mit folgender Anweisung ausführen:

./Welt

Headerdateien

Header enthalten Deklarationen (von Klassen und Funktionen beispielsweise) und Definitionen (von Typen und Makros). Es sind echte physische Dateien, die üblicherweise die Dateinamenserweiterung .h tragen. Sie werden in Codedateien eingelesen, um die in ihnen enthaltenen Deklarationen und Definitionen in diesem Code verfügbar zu machen. Das Codebeispiel importiert den Header Foundation/Foundation.h, damit der Compiler weiß, wie er mit den beiden @…-Konstrukten umzugehen hat.

Eigene Headerdateien schreiben Sie bei Objective-C in der Regel, um Klassen und ihre Schnittstellen zu deklarieren (diesen Aspekt werden wir uns im Kapitel 5, ansehen).

Header importieren

#import ist eine Objective-C-spezifische Präprozessordirektive zum Importieren von Headerdateien. Der Unterschied zum in C üblichen #include ist, dass #import sicherstellt, dass Header nur einmal importiert werden. Anders als Javas import oder C#s using macht #import nicht Namen bekannt, sondern liest Deklarationen und eventuell auch Definitionen ein.

#import kann auf zweierlei Weise verwendet werden: zum Import systemweiter Headerdateien und zum Import anwendungsspezifischer Headerdateien:

#import <…> importiert einen Systemheader.

#import "…" importiert einen anwendungsspezifischen Header.

Zwischen den spitzen Klammern bzw. Anführungszeichen steht der Name bzw. Pfad zu einer Headerdatei. Die verwendete Form steuert, wo nach der entsprechenden Datei gesucht wird, wenn der Name kein absoluter Pfad ist. Bei der ersten Form wird in einer (über Compilerschalter und Umgebungsvariablen erweiterbaren) Liste von Standardverzeichnissen gesucht. Bei der zweiten Form wird zuvor noch im aktuellen Verzeichnis gesucht.

Üblicherweise gibt es zu jeder Codedatei, deren Definitionen in anderen Codedateien genutzt werden sollten, eine eigene Headerdatei. Daneben gibt es übergeordnete Header, sogenannte Umbrella-Header, die viele in Zusammenhang stehende Header importieren und so gemeinsam importierbar machen. Der in unserem Beispiel verwendete Foundation.h-Header ist der Umbrella-Header für das Foundation-Framework, das das Fundament der Cocoa-Objective-C-API bildet.

Frameworks

Unter OS X und iOS werden Programmbibliotheken und andere Ressourcen zu sogenannten Frameworks gebündelt. Diese werden üblicherweise in /System/Library/Frameworks und /Library/Frameworks gespeichert und stehen allen Anwendungen zur Verfügung.

Frameworks können unter anderem Headerdateien mit den Deklarationen für die Features enthalten, die sie bereitstellen. Ein Framework kann mehrere Headerdateien enthalten. Folgendermaßen binden Sie einen Header aus einem Framework ein:

#import <Framework/Header.h>

Der Foundation/Foundation.h-Header, den unser Programm nutzt, ist ein Beispiel für einen solchen Framework-Header. Foundation ist das Framework, Foundation.h der Name der Headerdatei im Framework. Die Headerangaben mit #import werden vom Compiler zur entsprechenden Ressource im Framework-Bundle aufgelöst. Das heißt, dass der »Pfad« in der Headerangabe nicht dem tatsächlichen Dateipfad der Headerdatei entsprechen muss.

Der Foundation.h-Header ist der Umbrella-Header für das Foundation-Framework. Ein Umbrella-Header ist ein Metaheader, der (meist) keine eigenen Deklarationen enthält, sondern die Header für die verschiedenen Elemente eines Frameworks zusammenfasst. Wenn Sie eine Komponente eines Frameworks nutzen, sollten Sie in der Regel einen solchen übergeordneten Header verwenden, nicht die Header für einzelne Komponenten.

Bei der Kommandozeilenkompilation geben Sie Frameworks, gegen die gelinkt werden soll, mit dem Schalter -framework an.

Wenn Sie Xcode nutzen, werden die Frameworks, die standardmäßig für eine bestimmte Art von Anwendung genutzt werden, automatisch eingebunden. Müssen Sie zusätzliche Frameworks einbinden, können Sie das für das jeweilige Build-Target im Link Binary With Libraries-Abschnitt der Registerkarte Build Phases tun, den Sie in der Abbildung Abbildung 2.2 sehen:

Abbildung 2.2 Frameworks einbinden

Kapitel 3. Syntax

Objective-C erweitert C um eine Reihe von Syntaxstrukturen und Konzepten zur Unterstützung seiner dynamischen Variante der objektorientierten Programmierung. Dieser Abschnitt stellt sie kurz vor, damit Sie den Beispielen in den nachfolgenden Teilen des Buchs folgen können. Komplexere Elemente wie Objekte und Klassen werden an anderer Stelle noch ausführlicher betrachtet.

Klassen und Objekte

Objective-C unterstützt alle C-Datentypen, elementare (z. B. im ersten Beispiel oben char und int) wie komplexe (z. B. Structs oder Arrays). Daneben integriert es Strukturen zur Darstellung von Klassen und Objekten. Klassen sind Anleitungen für den Aufbau von Gegenständen, Objekte sind die konkreten Gegenstände, mit denen Objective-C-Code arbeitet.

Objective-C-Objekte referenzieren Sie in Ihrem Code über Variablen, die Zeiger auf einen Wert des entsprechenden Typs, d. h. der Klasse, sind, oder den generischen Objekttyp id haben, zum Beispiel:

NSString *string = @"Kansas";

oder:

id objekt = @"Kaninchenbau";

Objekte können mit Literalausdrücken (siehe Abschnitt „Literaldeklarationen“) definiert, von anderen Objekten geliefert oder mithilfe von Klassen konstruiert werden. Ausführlicher behandeln wir Objekte und Klassen in den Kapiteln 4 und 5.

Nachrichten

Die Interaktion mit Objekten und Klassen erfolgt über Nachrichten. Sie senden einem Empfänger (einer Klasse oder einem Objekt) eine Nachricht. Dieser prüft, ob er mit dieser Nachricht etwas anfangen kann, und reagiert gegebenenfalls entsprechend. Die Syntax zum Senden von Nachrichten hat folgende elementare Gestalt:

[Empfänger Nachricht]

Der Empfänger ist entweder eine im Kontext gültige Klasse oder eine im Kontext gültige Objektreferenz. Die Nachricht ist der Name einer Methode samt aller eventuellen Parameter, die auf dem Empfänger aufgerufen wird.

Konkret könnte das so aussehen:

[kaffeeMaschine kaffeeKochen]
[Auto neuesAuto]

Da der erste Buchstabe von kaffeeMaschine ein Kleinbuchstabe ist, wäre Ersteres konventionsgemäß eine Nachricht an das Objekt, das von der zuvor deklarierten und initialisierten Objektvariablen kaffeeMaschine referenziert wird. Das Zweite hingegen wäre eine Nachricht an die Klasse Auto, da der erste Buchstabe von Auto ein Großbuchstabe ist.

Nachrichten können parameterlos sein (wie die beiden Nachrichten oben), und sie können Parameter erwarten. Nachrichtenparameter folgen im Nachrichtennamen nach einem Doppelpunkt, wobei der Doppelpunkt Teil des Nachrichtennamens ist. Zum Beispiel sendet

[ich trinken: kaffee]

dem von ich referenzierten Objekt die Nachricht trinken: und übergibt dabei das von referenzierte Objekt.

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!

Lesen Sie weiter in der vollständigen Ausgabe!