Objective-C-Snippets
Eine Snippet-Sammlung für Objective-C.
Doku
Allgemeine Infos:
- The Objective-C Programming Language - Einführung in Objective-C
- iPhone Application Programming Guide - Einführung in die iPhone-Programmierung
- Object Ownership Policy - Regeln fürs Memory Management
Spezielle Themen:
- File and Data Management - Datei-Verwaltung
- Resource Programming Guide - Laden von Ressourcen
- Internationalization Programming Topics - Internationalisierung
- Information Property List Key Reference - Die Bedeutung der Keys in
Info.plist
- Der Key-Value-Datei, das bestimmt, wie das iPhone OS mit der Applikation umgehen soll. - iPhone Human Interface Guidelines - UI-Guideline
- Application Preferences - Wie man Eistellungen für die eigene App in der Settings-App einbindet.
- Concurrency Programming Guide - Wie man Operation-Objekte und Threads verwendet.
- Instruments User Guide - Wie man das Tool "Instruments" dazu verwendet, Memory-Leaks zu finden.
- Getting the User’s Current Location - Wie man die Geo-Position des iPhone bekommt.
API-Referenzen:
- UIKit Framework Reference - Die iPhone-Oberflächen-Bibliothek
Klassen
Header-Datei MyClass.h
:
@interface MyClass : MySuperClass
{
// member variables
int bla;
NSString* name; // strong typing
id data; // weak typing
}
// class method
+ (MyClass *)createMyClassWithString: (NSString *)name;
// instance method
- (void)doThis:(id)obj atIndex:(NSUInteger)index;
@end
Quell-Datei MyClass.m
:
@implementation MyClass
// private method ?? (TODO)
- (id)initWithString:(NSString *)aName
{
if (self = [super init]) {
name = [aName copy];
}
return self;
}
// class method (here: a factory method)
+ (MyClass *)createMyClassWithString: (NSString *)name
{
return [[[self alloc] initWithString:name] autorelease];
}
// instance method
- (void)doThis:(id)obj atIndex:(NSUInteger)index
{
...
}
@end
Messaging
// simple
[myObj doThis:anObject atIndex:0];
// nested messages
[[myAppObject theObject] doThis:[myAppObject objectToInsert] atIndex:0];
Properties
Details: Apple-Doku zu Declared Properties
Property-Definition (.h
-Datei):
@interface MyClass : MySuperClass
{
}
// explicite property definition (getter and setter)
-(type)propertyName;
-(void)setPropertyName:(type);
// Convenience syntax
@property BOOL flag;
// Convenience syntax with custom options
@property (copy) NSString *nameObject; // Copy the object during assignment.
@property (readonly) UIView *rootView; // Declare only a getter method.
@end
Property-Implementierung (.m
-Datei):
@implementation MyClass
// explicite property implementation (getter and setter)
-(type)propertyName
{
return ...;
}
-(void)setPropertyName:(type)
{
...
}
// Directive which lets the compiler generate the getters and setters
@synthesize flag, nameObject, rootView;
@end
Property-Aufruf:
// convenience syntax for getting properties
type bla = [myObj propertyName];
type bla = myObj.propertyName;
// convenience syntax for setting properties
[myObj setPropertyName:newValue];
myObj.propertyName = newValue;
Property-Observing
Siehe: Apple-Doku zu KVOBasics
{
[targetObj addObserver:self forKeyPath:@"propertyName"
options:NSKeyValueObservingOptionNew context:nil];
...
[targetObj removeObserver:self forKeyPath:@"propertyName"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqual:@"propertyName"]) {
id value = [change objectForKey:NSKeyValueChangeNewKey];
...
}
// call super method, if super class does property observing as well
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
Protokolle
Details: Apple-Doku zu Protocols.
Protokolle sind in Objective-C das, was in den meisten anderen Sprachen "Interfaces" genannt wird. Also eine Definition von Methoden, die eine Klasse implementieren muss, wenn sie dem Protokoll entsprechen will - ohne den Zwang von einer bestimmten Klasse erben zu müssen.
@protocol MyProtocol
- (void)myProtocolMethod;
@end
Strings
// shorthand notation for creating a string
NSString *myString = @"My String\n";
// Formatting
NSString *anotherString = [NSString stringWithFormat:@"%d %s", 1, @"String"];
// Create an Objective-C string from a C string
NSString *fromCString = [NSString stringWithCString:"A C string"
encoding:NSASCIIStringEncoding];
Arrays
Array iterieren:
// Create an array. Last object must be nil!
NSArray *arr = [NSArray arrayWithObjects: @"a", @"b", @"c", nil];
// Iterate with for..in:
for (id item in arr) {
NSLog(@"item: %@", item);
}
// Iterate with index:
int i;
for (i = 0; i < [arr count]; i++) {
id item = [arr objectAtIndex:i];
NSLog(@"item #%@: %@", i, item);
}
I18N
I18N einrichten
- In Xcode im Projektbaum Rechtsklick auf "Resources".
- "Add -> New file..." auswählen.
- Auf der linken Seite "Mac OS X -> Resource" auswählen, auf der rechten Seite "Strings File". Dann "Next" anklicken.
- Als Name "Localizable.strings" verwenden und "Finish" anklicken.
- Rechtsklick auf die neue Datei und "Get info" auswählen.
- Unter "General" auf "Make File Localizable" klicken.
Hinweis: Xcode stellt Localizable.strings so dar, als hätten sie mehrere Zweige (für die verschiedenen Sprachen). Im Dateisystem gibt es dagegen mehrere Kopien von Localizable.strings in verschiedenen Unterverzeichnissen (English.lproj, German.lproj, ...).
Damit hat man eine Default-Lokalisierung für Englisch.
Wenn man vorerst nur eine Sprache (z.B. deutsch) verwendet: Am besten in die englische Version von Localizable.strings die deutschen Strings eintragen. Denn mit einer gefüllten deutschen und einer leeren englischen Variante kann man sich leicht Probleme einfangen. Später kann man dann eine deutsche Lokalisierung hinzufügen und dorthin die ganzen fertigen Texte kopieren und anschließend die englische Version übersetzen.
I18N verwenden
Im Code verwendet man dann folgendes Konstrukt für alle Strings:
exampleLabel.text = NSLocalizedString(@"key", @"comment");
Die Entsprechung in den Localizable.strings sieht dann so aus:
/* comment */
"key" = "value";
Es gibt auch ein Tool, das den Code nach NSLocalizedString-Aufrufen absucht und Einträge in den Localizable.strings erzeugt. Aber man kann es auch von Hand machen: Code schreiben, der den String verwendet, und dabei gleich den Localizable-Eintrag ergänzen.
Logging
Log-Aufruf:
NSLog(@"Contents: %@", contents);
Das Log kann man in Xcode im Menü "Run -> Console" öffnen.
iPhone-API
Programm-Icon ohne Glanz
Auf dem Gerät testen
Weblinks:
- iOS Development Guide - Managing Devices and Digital Identities
- iOS Development Guide - Running Applications
Vorbereitung:
- Man muss einen Developer Account haben und das "iOS Developer Program" gekauft haben.
- Bei https://developer.apple.com/iphone/ mit Developer Account einloggen
- Rechts im Kasten "iOS Developer Program" auf "iOS Provisioning Portal" drücken.
- Links auf "Certificates" klicken und nochmal einloggen (warum auch immer)
- Wenn unter "Your certificate" noch nichts steht:
- Auf "Request Certificate" klicken
- Die Anleitung befolgen, um mit der Schlüsselbundverwaltung ein Private/Public-Key-Paar und einen Certificate Signing Request (CSR) zu generieren und auf der Platte abzulegen.
- Den CSR auf der Seite mit der Anleitung hochladen.
- Nochmal mit dem Developer Account nochmal einloggen (warum auch immer)
- Von der Certificates-Seite weg- und wieder hin-navigieren. Das Zertifikat sollte nun approved sein.
- Zertifikat herunterladen.
- Auch Zertifikat von Apples "worldwide developer relations CA" (WWDR-CA) herunterladen.
- Beide Zertifikate in der Schlüsselbundverwaltung importieren: Menü -> Ablage -> Objekt importieren
- Das Zielgerät anschließen.
- xCode-Organizer öffnen: Im xCode-Menü -> Window -> Organizer
- Im Organizer das Zielgerät auswählen und "Use for Development" drücken (und mit dem Developer Account einloggen)
- Falls dies früher schon mal probiert wurde, aber unter "Provisioning" nichts steht: Rechts auf das Zielgerät klicken und "Add Device to Provisioning Portal" wählen.
- Im xCode-Menü "Project -> Edit Project settings" wählen.
- Auf den "Build"-Tab wechseln
- Unter "Code Signing -> Code Signing Identity -> Any iPhone OS Devive" "iPhone Developer (currently matches ...)" auswählen.
Bauen:
- Im Projektfenster in xCode links oben als Ziel "Device ..." auswählen.
- "Build and Run" drücken.
Was an Objective-C nervt
Schwache Typisierung
Man kann einer typisierten Variablen einen Pointer zu einem Objekt von einem anderen (falschen) Typ zuweisen. Der Zugriff auf dieses Objekt kracht erst bei der Benutzung, also potentiell 10 Ecken nach dem eigentlichen Fehler.
Man kann Methoden auf nil
aufrufen. Das führt zu keinem Fehler. Das Ergebnis ist wieder nil
- auch wenn die betreffende Methode niemals nil
zurückgeben würde.