Objective-C-Snippets

Eine Snippet-Sammlung für Objective-C.

Doku

Allgemeine Infos:

Spezielle Themen:

API-Referenzen:

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

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

Siehe: http://developer.apple.com/iphone/library/documentation/userexperience/conceptual/mobilehig/IconsImages/IconsImages.html

Auf dem Gerät testen

Weblinks:

Vorbereitung:

Bauen:

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.