Programmieren mit Swift - Für macOS und iOS
Programmieren mit Swift - Für macOS und iOS
Aufbau von Klassen

Im Header einer Klasse befinden sich jetzt nur noch Methodendeklarationen und Eigenschaften (Properties), die für andere Programmteile öffentlich gemacht werden müssen. Instanzvariablen müssen nicht länger im Header deklariert werden, um in der gesamten Klasse bekannt zu sein.
#import <UIKit/UIKit.h>

@interface Person : NSObject

@property (nonatomic, assign) int age;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *firstName;

- (void)sayYourName;
- (void)setAgeByBirthday:(NSDate *)birthday;

@end
Der Compiler erzeugt aus jeder @property-Definition automatisch Accessor-Methoden, die so genannten Getter und Setter, mit denen auf die Eigenschaften der Klasse zugegriffen werden kann. Zusätzlich werden ebenfalls automatisch Instanzvariablen angelegt. Diese verwenden den gleichen Namen wie die deklarierte Eigenschaft, beginnen aber mit einem Unterstrich. Die in der Vergangenheit erforderlichen @synthesize-Anweisungen müssen nicht mehr programmiert werden.
<#import "Person.h"

@implementation Person

- (id)init
{
    self = [super init];
    if (self)
    {
        _age = 0;
        _name = @"Meier";
        _firstName = @"Max";
    }
    return self;
}

- (void)sayYourName
{
}

- (void)setAgeByBirthday:(NSDate *)birthday;
{
}

@end
Falls gewünscht kann auch von innerhalb der Klasse der Zugriff auf die Instanzvariablen über die Eigenschaften geschehen. Der Aufruf erfolgt dann über den Objekt-Bezeichner self, gefolgt von einem Punkt und dem Namen der Eigenschaft. Diese Vorgehensweise ist besonders sinnvoll, wenn ein Getter oder Setter manuell implementiert wurde, um fehlerhafte oder unpassende Werte für eine Eigenschaft zu vermeiden.
Im folgenden Beispiel wird der Eigenschaft age ein Wert von -5 zugewiesen. Da der Aufruf über self und somit über die Eigenschaft geschieht, greift der Setter setAge, wo der übergebene Wert kontrolliert und korrigiert wird.
- (id)init
{
    self = [super init];
    if (self)
    {
        self.age = -5;
        self.name = @"Meier";
        self.firstName = @"Max";
    }
    return self;
}

- (void) setAge:(int)age
{
    if (age < 0)
    {
        _age = 0;
    }
    else
    {
        _age = age;
    }
}
Benötigt eine Klasse, zusätzlich zu den Eigenschaften, weitere private Instanzvariablen, können diese direkt nach @implementation in der .m-Datei hinterlegt werden. In diesem Block aus geschweiften Klammern ist eine Zuweisung von Werten für die Variablen allerdings nicht möglich.
#import "Person.h"

@implementation Person
{
    bool didCalculateBirthday;
    NSString *title;
}
...
Auch die manuell programmierten Instanzvariablen können innerhalb der gesamten Klasse angesprochen werden. Der Zugriff erfolgt allerdings nicht über self, und der Variablenname beginnt in der Regel auch nicht mit einem Unterstrich, obwohl es ihnen natürlich freisteht, Ihre Variablen beliebig zu benennen.
- (id)init
{
    self = [super init];
    if (self)
    {
        self.age = -5;
        self.name = @"Meier";
        self.firstName = @"Max";
        title = @"Doktor";
        didCalculateBirthday = false;
    }
    return self;
}
Falls es erforderlich sein sollte, können für eine Klasse auch private Eigenschaften deklariert werden. Diese stehen dann allerdings nicht im Header, sondern in einem zusätzlichen Interface in der .m-Datei.
#import "Person.h"

@interface Person()

@property(nonatomic, assign) double salary;
@property(nonatomic, copy) NSString *company;
@property(nonatomic, copy) NSString *department;

@end

@implementation Person
...
Der Zugriff von innerhalb der Klasse erfolgt auch hier wieder über den Namen der Eigenschaft in Verbindung mit self oder direkt auf die vom Compiler erzeugte Instanzvariable mit einem führenden Unterstrich.
_salary = 500000;
self.department = @"Development";
_company = @"Yoyodyne";
Die in der Implementierung deklarierten Properties haben allerdings den Nachteil, dass sie nicht wirklich vollständig privat sind, denn auch für diese Eigenschaften generiert der Compiler Getter und Setter. Zwar entziehen sich solche Eigenschaften dem normalen Zugriff über die Punkt-Notation, mit performSelector kann aber trotzdem mit dem Property gearbeitet werden, ohne dass der Compiler Warnungen ausgibt. Ein vorhergehende Aufruf von respondsToSelector kann prüfen, ob eine Accessor-Methode zur Verfügung steht.
Person *person = [[Person alloc] init];

bool responds = [person respondsToSelector:@selector(company)];
if (responds)
{
    NSString *companyName = [person performSelector:@selector(company)];
    NSLog(@"%@",companyName);
}