Cocos2d und ARC

Hallo Zusammen,

Wir haben ja vor kurzem gelernt wie man das Cocos2d Framework installiert und eigentlich könnten wir nun richtig loslegen.  Es lohnt sich jedoch vorher noch etwas Zeit zu investieren um das Automatic Reference Counting (ARC) zu aktivieren. Dadurch sparen wir hinteraus sehr viel Zeit. Aber was ist Automatic Reference Counting? Objecte die während der Laufzeit des Programms erstellt werden verbrauchen etwas Arbeitsspeicher des jeweiligen Gerätes. Normalerweise müssen wir als Programmierer uns bei Objective-C darum kümmern, dass Objecte die wir nicht benötigen diesen Speicher wieder freigeben. Hierfür hat man zum Beispiel retain und release benutzt. Mit retain drückt man aus, dass man dieses Objekt benötigt und es nicht zerstört werden darf. Release hingegen sagt das genaue Gegenteil – wir brauchen das Objekt nicht mehr.

-(void)BeispielMethode{
      NSDate *now = [[NSDate now] retain];
      // tolle Algorithemn mit now abarbeiten
      [now release]; 
}

Vielleicht ist euch aufgefallen, dass wir diese Anweisungen in der Vergangenheit nie benutzt haben? Nun unsere bisherigen Programme waren diesbezüglich halt einfach schlecht :) Sie hätten Speicher gefressen und wären irgendwann abgestürzt. Aber das braucht uns nun nicht mehr zu kümmern, denn nun haben wir ARC. In unserem Code verzichten wir komplett auf retain, release, autorelease und ähnlichem.

Leider ist Cocos2d noch nicht an so angepasst, dass es ARC benutzen kann. Natürlich gibt es auch hierfür eine Lösung. Wir sagen einfach die Cocos2d Bibliotheken sollen ihre Arbeitsspeicher selber verwalten (also ohne ARC) und dass ARC nur für die Klassen zählt die wir selber erstellen.

Aber zunächst knipsen wir ARC an, falls es nicht schon bei der Erstellung des Projektes geschehen ist. Dazu gehen in die Build Settings des Projektes und setzen den Menupunkt Objective-C++ Automatic Reference Counting auf YES.

ARC enabled

Anschließend müssen wir Edit > Refactor > Convert to Objective-C ARC XCode ausführen. Und tada:

29 Fehler :(
Natürlich ist das kein Problem. Es gibt eine Möglichkeit XCode zu sagen, dass ARC nur für bestimmte Klassen angewendet werden soll. Die von ARC ausgenommenen Klassen kümmern sich dann selbst um ihre Speicherverwaltung. Wir wollen alle Klassen des Cocos2d Frameworks so behandeln.

Wir markieren also das Target unseres Projektes. Anschließend gehen wir im Reiter Build Phase in den Abschnitt Compile Sources. Dort werden nun alle Klassen markiert die ihren Speicher selbst verwalten sollen. In dem Beispiel vom Screenshoot (also bei einem frischen Cocos2d Projekt) sind das alle außer HelloWorldLayer.m, AppDelegate.m, main.m und IntroLayer.m

Sind die Klassen markiert drücken wir Enter und tragen in der aufgetauchten Eingabebox „-fno-objc-arc“ ein. Anschließend wieder Enter.

Wir haben immernoch Fehler in den bisher nicht berücksichtigten Klassen die wir nun der Reihe nach abarbeiten.

main.m
Hier muss die main Funktion mit dem folgenden ersetzt werden:

int main(int argc, char *argv[]) {
    @autoreleasepool {
        int retVal = UIApplicationMain(argc, argv, nil, @"AppController");
        return retVal;
    }
}

AppDelegate.m und HelloWorldLayer.m
Hier stören noch alle release und dealloc Befehle. Wir brauchen Sie nicht mehr und löschen sie oder kommentieren sie aus.

AppDelegate.h
Hier gibt es eigentlich keinen Fehler. Allerdings ist der ursprüngliche Code nicht ARC gerecht. Es wurde zum Beispiel bei der property Deklaration retain durch strong ersetzt.
Wir nehmen Anpassungen vor, um sauberen Code zu haben. Das Interface sieht anschließend so aus:

@interface AppController : NSObject 
{
	UIWindow *window_;
	UINavigationController *navController_;
	CCDirectorIOS	*__unsafe_unretained director_;	
}

@property (nonatomic, strong) UIWindow *window;
@property (readonly) UINavigationController *navController;
@property (unsafe_unretained, readonly) CCDirectorIOS *director;

@end

Es fällt natürlich sofort *__unsafe_unretained ins Auge. Mit dieser Deklaration sagen wir Xcode, dass sich ARC um dieses Objekt nicht kümmern braucht, sondern dass der Speicherbedarf anderswo (hier im Cocos2d Framework) verwaltet wird.

Jetzt haben wir es geschafft. Speicherverwaltung ist ab jetzt kein Thema mehr und wir können trotzdem die Vorzüge des Cocos2d Frameworks nutzen.

Bis zum nächsten mal.

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.