How To Enable ARC in a Cocos2D 2.X Project

Tony Dahbura

This is a post by Tutorial Team Member Tony Dahbura, an independent iOS developer with FullMoon Manor LLC. You can also find him on .

Learn how to use ARC in a Cocos2D project!

Learn how to use ARC in a Cocos2D project!

Automatic Reference Counting (or ARC for short) makes memory management in your apps much easier.

ARC’s major benefit is freeing you from worrying about whether you cleaned up that sprite or image from your game. As you probably know, even a small memory leak can make your game behave unpredictably. And after all, nothing kills a great game experience like an application crash while in the heat of the action.

Another benefit of ARC is that since it takes care of memory management for you, it allows you to focus on game development. Every minute you have for development lets you get your app done faster! What’s not to like about that?

However, by default the Cocos2D templates do not have ARC enabled. So a common question is “how can I use ARC in a Cocos2D project?” This tutorial will show you how to do exactly that! :]

First you’ll build a simple ARC-enabled project from scratch. Then, it’s Return of the Ninjas Going Pew-Pew! You’ll take the classic game and learn how to update games made with Cocos2D 1.X to Cocos2D 2.X.

Ready to expand your ninja-skills? Keep reading to get started!

Getting Started

This tutorial is going to show you two ways to convert a project to use ARC. First, I’ll show you the manual way of doing things, for the learning experience. Then, I’ll show you a simpler way to save time.

In a rush? If you don’t have much time and just want to skip to the “easy way” of doing things, feel free to skip down to the “Xcode At Your Service” section!

Using ARC with Cocos2D v2.x is a half-and-half option – meaning that the Cocos2D core code will not be ARC-compliant, but the files for your own app will be. This way, you will get the benefit of using ARC, without the library creators having to go back and rewrite all those routines to be ARC-compliant.

First things first: if you don’t have Cocos2D v2.x installed, then you can download Cocos2D v2.x from the official website.

After you download and extract the code, install the Cocos2D project templates. Open a Terminal window to the directory where you extracted Cocos2D, and enter the following command:

./ -f -u

The above command will install the necessary Cocos2D templates so that they will be available via Xcode.

As with most example programming projects, you’re going to create a Hello World! project. But this time, in addition to using Cocos2D, the project will also be ARC-enabled!

Start up Xcode and create a new Cocos2D v2.x project by selecting the iOS\Cocos2D v2.x\Cocos2D iOS template. Make sure to select the Cocos2D v2.x template list if you also have the older Cocos2D 1.x libraries installed. Click Next.

Name the project HelloWorldCocos, set the Company Identifier (if necessary, or you can leave it as-is) and change the Device Family to iPhone. Click Next, select a location for your project on your hard disk, and click Create.

Now build and run the template to make sure everything is working correctly. You should see the following:

Note: If your app appears in portrait mode instead of landscape, simply go to the project settings by tapping on the project root in the Project Navigator, select the HelloWorldCocos target, and select the Summary tab. Then disable the portrait orientations from the list of supported interface orientations.

Your app currently runs using the new Cocos2D libraries and without ARC, meaning that the standard memory management retain/release model is in use.

Hello, World! With ARC

It’s time to make your app ARC-enabled!

In Xcode’s Project Navigator (left sidebar), select your project root, then select the HelloWorldCocos target in the middle panel (if it is not already selected), then Build Phases, and expand the Compile Sources section (tap the triangle next to the section name to expand it).

You are going to mark the core Cocos2D files as not ARC-compliant, and hence allow them to continue to use the retain/release model. This is a new feature in Xcode: the ability to select a block of files and apply an option to them.

Select the first file in the list, CCAction.m, by clicking once on it. Then scroll the list of files to the bottom, hold down the shift key, and click on vec4.c. You should see a blue block similar to the following:

Double-click in the blue area (or you can tap Return – sometimes that works better) and a dialog box will drop down. In this dialog box, type the following and press Return:


All the selected files will now have the -fno-objc-arc compiler flag to the right of them, similar to the following:

You’ve just told the compiler not to apply ARC to these files. Instead, the compiler would treat them as it did before ARC came along.

Let’s turn on ARC for the remaining files.

Select the Build Settings tab and make sure All and Combined are selected. Scroll the display until you see Apple LLVM compiler 4.1 – Language at the top of the window.

Approximately 18 lines from the top of the options is one called Objective-C Automatic Reference Counting. (You can also simply type in ARC in to the search field to find the ARC setting.) It contains a drop down with a value of Yes or No. Right now the value is No. Select the value and change it to Yes.

Build your application.

You will see a series of errors on several files, in this case main.m, AppDelegate.m, and HelloWorldLayer.m. These files were not marked with the -fno-objc-arc setting earlier, and the compiler is unhappy that they are not ARC-compliant.

Let’s fix that!

Select the Project Navigator (the folder icon underneath the Run button on the left sidebar) and expand the Supporting Files folder. Select the main.m file:

The use of NSAutoReleasePool is not valid under ARC. So replace the main method with the following:

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

The ARC model uses the @autoreleasepool statement where you enclose the code that will use the pool within braces. This is much cleaner and easier to follow.

Build your project again.


Not a pretty picture. :]

Xcode indicates that there are still code issues in AppDelegate.m and HelloWorldLayer.m. The main problems are the use of release and calling [super dealloc], since ARC automatically handles making these calls.

You can tap on each line shown on the Issue Navigator (the view shown above) and Xcode will take you to the relevant line in the relevant file. In this way, you can move through all the issues quickly, removing the release and [super dealloc] calls. Do that now.

Build your project again, and if you removed all the offending instances of release and [super dealloc], your code should compile fine. If you see any remaining issues, go through them and fix as before.

Even though your code should now be compiling fine, there is one more file to fix, and that is AppDelegate.h. This file contains a property, and ARC needs to know how it should be handled.

The specific property is the director_ property, which Cocos2D has commented in the template as a weak reference. Modify your AppDelegate.h file so that it looks like the following, in order to let ARC know about the weak reference:

#import <UIKit/UIKit.h>
#import "cocos2d.h"
@interface AppController : NSObject <UIApplicationDelegate, CCDirectorDelegate>
	UIWindow *window_;
	UINavigationController *navController_;
	CCDirectorIOS	*__unsafe_unretained director_;	// weak ref
@property (nonatomic, strong) UIWindow *window;
@property (readonly) UINavigationController *navController;
@property (unsafe_unretained, readonly) CCDirectorIOS *director;

Notice the addition of the __unsafe_unretained to the variable declaration and the @property declaration, as well as the change to the window property, where now it’s declared as strong instead of retain. While strong and retain essentially mean the same thing (that the property will be retained), strong is the correct form to use with ARC.

Build and run again.

Woohoo! You are up and running with ARC now!

You have your project set to use ARC, and you are using the Cocos2D library. This project is ready for your gaming creativity to take flight. :]

Now that you understand how to start a new Cocos2D project and manually convert it to support ARC, let’s look at an alternative method of accomplishing this, with some assistance from Xcode.

Xcode At Your Service

Apple recognized that many developers would want to embrace ARC, and has provided tools to assist in the transition. Since you know the steps to do the work manually, and understand what is involved, let’s look at converting an older Cocos2D project from 1.0 to 2.x and enabling ARC support.

Note: You can use the same techniques shown in this section to take any of the older tutorials from this site written for Cocos2D 1.X, and update them to Cocos2D 2.X and ARC!

Also, you can use these techniques to convert a new project made with the Cocos2D template to enable ARC just as you did in the last section – but even easier! :]

And what better place to use your new skills than the project from the first ever Cocos2D tutorial on Ray’s website? That’s right, the Ninjas Going Pew-Pew!

Ninjas Going Pew-Pew!

Ninjas Going Pew-Pew!

You are not going to spend a lot of time going over the ins and outs of the game itself, as the original tutorial does this wonderfully. Instead, you are going to focus on the necessary steps to get it working with Cocos2D v2.x, and then enabling ARC.

To save time, download the source project from here.

Extract the ZIP file to a convenient location. You will selectively grab pieces from this project and add them to the new converted version of the game that you will create.

Start up Xcode and create a new project using the iOS\Cocos2D v2.x\Cocos2D iOS template, and click Next. Name the project PewPewNinjas, set the Device Family to iPhone, click Next, choose a folder to save your project in, and click Create.


First add the game resources, including the sound effects and graphics, from the old game.

Locate the folder where you extracted the original game and open the Resources folder. Select the background-music-aac.caf file by clicking on it. Then hold down the Command key and click on ItunesArtwork, logo6.png, pew-pew-lei.caf, Player.png, Projectile.png, and Target.png. Drag these files over to your Xcode window and place the cursor right over the folder named Resources, and let go.

When the dialog box appears, make sure the Copy items into destination group’s folder is checked, and that PewPewNinjas is checked under Add to targets.

Click the Finish button. You have just copied over the graphic and sound effects into your new Cocos2D v2.x project! The Resources folder of your project should now look like this:

Build and run your application.

The application will show the same old Hello World screen, since you have not modified the code yet. It’s time to fix that!

One advantage of selectively adding files is that you can take advantage of new capabilities in the template code. This is the case in this effort, since you should be using the new AppDelegate files rather than bringing the older Cocos2D 1.x files into the project.

Once again, go to your folder with the older game code and open the Classes folder. Select all the files from GameConfig.h to HelloWorldScene.m.

Drag these files into your new Xcode project’s PewPewNinjas folder. Make sure the Copy items into destination group’s folder is checked and that PewPewNinjas is checked for Add to targets on the dialog.

Click the Finish button. Your Xcode project file view should look something like this:

You might wonder why some class files weren’t copied over. They simply aren’t needed with the new model.

Now let’s see what it will take to get PewPewNinjas running under Cocos2D 2.x by building the project again.

Xcode will complain about multiple errors. These are due to changes to the Cocos2D API since 1.x. Let’s go through and fix those issues.

First, CCColorLayer does not exist in Cocos2D v2.x, so you need to adjust the files accordingly.

Select GameOverScene.h and change the @interface line to:

@interface GameOverLayer : CCLayer {

Then, select HelloWorldScene.h and change the @interface line to:

@interface HelloWorld : CCLayer

The older CCColorLayer also allowed setting the layer’s background color using initWithColor:. You need to fix this as well. Select GameOverScene.m and change the first line in GameOverLayer’s init from:

	if( (self=[super initWithColor:ccc4(255,255,255,255)] )) {


	if ((self=[super init])) {

Save your changes, then open HelloWorldScene.m. Locate the same line in HelloWorld’s init:

	if( (self=[super initWithColor:ccc4(255,255,255,255)] )) {

Change it to:

if ((self=[super init])) {

Build and run again.

Whoa, what happened? Where is your game?

The Cocos2D v2.x startup sequence begins with the AppDelegate. The AppDelegate loads the IntroLayer, which pauses for a second and then calls makeTransition, which then displays the HelloWorldLayer scene.

That is not your game code, but the standard HelloWorld scene from the template.

Select IntroLayer.m. You need to tell it about the new HelloWorldScene class and remove the import for the template’s HelloWorldLayer.h. The final #import section should look like:

// Import the interfaces
#import "IntroLayer.h"
#import "HelloWorldScene.h"

Scroll to the bottom. Replace makeTransition: with the following:

-(void)makeTransition:(ccTime)dt {
    [[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.0 scene:[HelloWorldScene node]]];

Then delete HelloWorldLayer.h and HelloWorldLayer.m from the project, since they are not needed anymore.

Build and run.


Your ninjas and aliens move in the dark. In may be in their nature to do such a thing, but you want to keep an eye on them! What happened?

Remember how you removed the initWithColor:ccc4(255,255,255,255) bit? That set the background color and alpha modes for the scenes. Since this call does not exist in Cocos2D v2.x, the scene must be set up to using the new API calls in Cocos2D 2.x to get the white background back.

In Cocos2D v2.x, this is done using a glClearColor(r,g,b,a) call directly to the openGL view.

Since the entire game uses a white background, what better place to set this than in the AppDelegate?

Open AppDelegate.m, locate application:didFinishLaunchingWithOptions:, scroll down to where the scene is added to the director, and enter:

glClearColor(255, 255, 255, 255);  //set your background to all white for all the scenes

Build and run.

Yippee! Your game is now running under Cocos2D v2.x, and it has the right background. Go grab a drink and take five. :] When you come back, you’ll begin the process of making the game ARC-compliant!

Here is the code for the PewPewNinjas app up to this point.

Enabling ARC For Your New Game Using Xcode

Are you back? OK, time to get to work again. :] In the last section, you took the old Cocos2D 1.x version of PewPewNinjas and converted it to run using Cocos2D 2.x. But the project is still old-skool: it isn’t ARC-compliant. Time to change that!

Open your project (if it isn’t already) and from the Xcode menu, select Edit\Refactor\Convert to Objective-C ARC.

Make sure the checkbox at the top is unchecked.

Select the drop-down arrow next to so that it expands to show all the source files in the project. Scroll to the bottom of the list of files and select main.m, AppDelegate.m, IntroLayer.m, GameOverScene.m, and HelloWorldScene.m.

This dialog asks for files that should be checked and corrected to be ARC-compatible. Since the Cocos2D core is not ARC-compliant, there should not be any files checked other than the five mentioned above. Click the Check button. You will be greeted by a dialog box asking you to confirm the changes.

Click Next.

After a brief period of analysis, you will see the five files you selected, plus some additional .h files that also need fixing. There’ll also be a split view where the left pane shows the needed changes, and the right pane shows the original source.

Click on AppDelegate.m and note the analyzer changes.

Look through each of the files so you can get a feel for the code changes made by Xcode.

Note that in AppDelegate.m, the analyzer completely removed the dealloc method. This is different from what you did earlier, where you removed the release calls but left the method intact. Of course, since there is no code in dealloc, it makes sense to remove the method completely.

This is a great time to learn about some of the differences between ARC and the traditional model of memory management. You will notice some of the following:

  • The retain keyword is replaced by strong.
  • All release and autorelease statements are removed.
  • [super dealloc] is removed.
  • The dealloc method is altogether removed where it isn’t needed/used.

Since you have no issues with the changes suggested by Xcode, click the Save button. You will be prompted as to whether Xcode should create a snapshot of your project before making all these changes. In this case, since it is a conversion from the base template, just select Disable.

You will now be returned to your project with the necessary changes in place for ARC. It’s as simple as that!

Summary of Changes Xcode Performed

Here’s a quick reference to what the wizard did for you:

In AppDelegate.h:

CCDirectorIOS	*__unsafe_unretained director_;
@property (nonatomic, strong) UIWindow *window;
@property (unsafe_unretained, readonly) CCDirectorIOS *director;

In AppDelegate.m:

  • Removed method – (void) dealloc

In GameOverScene.h:

@property (nonatomic, strong) CCLabelTTF *label;
@property (nonatomic, strong) GameOverLayer *layer;

In GameOverScene.m:

  • Removed two – (void) dealloc methods
[[CCDirector sharedDirector] replaceScene:[[HelloWorldScene alloc] init]];

In HelloWorldScene.h:

@property (nonatomic, strong) HelloWorld *layer;

In HelloWorldScene.m:

  • Removed method – (void) dealloc under HelloWorldScene implementation
  • Removed [targetsToDelete release];
  • Removed [projectilesToDelete release];
  • Modified method – (void) dealloc under HelloWorld implementation
- (void) dealloc
	// in case you have something to dealloc, do it in this method
	// in this particular example nothing needs to be released.
	// Cocos2D will automatically release all the children (Label)
	_targets = nil;
	_projectiles = nil;
	// don't forget to call "super dealloc"

In main.m:

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

Look around and check out the Build Settings for your project – you will see that the ARC flag has been set to YES.

Now build and run one final time. :]

Enjoy your new Cocos2D v2.x game utilizing ARC!

Where To Go From Here?

Here is the complete code for PewPewNinjas with the ARC conversions.

You covered several topics in this tutorial, including converting a Cocos2D game from 1.x to 2.x. The Cocos2D site has a migration guide that discusses code migration from 1.x to 2.x in detail.

To learn more about ARC and various issues you might run into converting projects, check out Chapters 2 and 3 in iOS 5 by Tutorials, Beginning and Intermediate ARC.

I hope you enjoyed this tutorial, and have fun converting your own Cocos2D projects to run under Cocos2d 2.x and ARC! I’d love to hear about your own conversion experiences in the forums.

This is a post by Tutorial Team Member Tony Dahbura, an independent iOS developer with FullMoon Manor LLC. You can also find him on .

Tony Dahbura

Tony is a hardware/software engineer from Virginia with more than 30 years software development experience. His first “real” computer was an Apple ][ and he has loved Apple Systems ever since! Tony has been working with iOS for about 3 years. He has worked on server systems, Java development, and various flavors of Unix.

In his spare time, after attending his kids sporting events, he does some independent software development work under FullMoon Manor LLC, helping folks realize the joy of custom apps to meet their needs. You can follow him on Twitter or connect on LinkedIn.

User Comments


  • Thank you so much for posting this! I almost gave up doing some of the Cocos2D tutorials, silly me. Other methods to make Cocos2D arc compatible were blowing up my computer.

    Where would newbies be without this site?
  • great tutorial. This is exactly what I needed to get back to cocos2D. I stopped developing for cocos2d in the 0.9.8 era and when i started again after all this time it left me confused. Thanks for this tutorial.
  • I disagree flagging on a per-source-file basis with -fno-objc-arc. It is a way to do it, but it will be pretty hard to maintain your code when you update Cocos2d! Instead take a look at another approach :

    Here's a quote from Steffen in that tut:
    Warning: Some recommend to use the -fno-objc-arc Compiler Flag to disable ARC on a per-source-file basis. This is only helpful if you have very few source code files which require this flag where an extra static library target would be overkill. Since youll have to add the flag to each cocos2d source code file individually one-by-one and there being anywhere between 100 and 150 source files, I strongly discourage going down this road. Plus it will be a maintenance nightmare whenever you upgrade cocos2d.
    World of A
  • @World of A: Heh, and I disagree with that :]

    Code: Select all
    Since youll have to add the flag to each cocos2d source code file individually one-by-one and there being anywhere between 100 and 150 source files, I strongly discourage going down this road.

    That is actually untrue - if you select the files and hit "Enter" in Xcode you can set all of them at once.

    So upgrading to a new version of Cocos2D is no problem, since setting that flag on the files only takes < 10 seconds. :]

    I'm not saying the library approach is bad - there are some nice things about doing it that way - but this way has the advantage of being nice and easy.
  • I just updated cocos to latest version cocos2d-iphone-2.1-rc0a, followed all the steps, seems working fine but there is a warning in appDelegate.m which worries me.

    inside the method:
    Code: Select all
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
       [director_ setDelegate:navController_];

    the warning says:
    sending 'UINAvigationController *_strong to parameter of incompatible type 'id<CCDirectorDelagete>'

    Is this something I should ignore, or should I do anything else.
  • I tried the static library approach... ran into errors. this method worked for me, so yes this is easier :)
  • I've followed all the steps you've suggested, but when I build I get an error message: 'Expected ';' at end of declaration list' for this line in the AppDelegate.h file:

    CCDirectorIOS *_unsafe_unretained director_; // weak ref

    which seems strange, since the ';' is there. I'm using Xcode 4.5.2.
  • Wow. I've been all over the internet in search of a solution to all my memory management problems. This conversion to ARC pretty much solved them all. Thank you so much for this tutorial!
  • Hello all! Hopefully someone can help me with this problem.

    In my current game using Cocos2D 2.1 with ARC, I have a MapScene that initializes a TMX Map and is loading object groups and creating an Event object for each object found on the map. The game takes on elements from a top down 2D RPG. The Event class represents NPCs. This is all working perfectly. I reuse this MapScene when changing maps. So from MapScene I replace the scene with a new MapScene, inserting the new TMX map to load.
    Code: Select all

    Now my problem with memory comes in when I change the scene to Map1, then to Map2, and back to Map1. When reloading Map1 the memory jumps about 4MB everytime, while the textures and data are supposed to either be stored in Cocos2D caches, or cleaned up on scene replacement. This memory jump also occurs when I am on MapScene:(Map1) and replace the scene with a new MapScene:(Map1). Am I wrong to believe that the reloading the same scene with the same map and objects should not increase the memory by 4MB each time, never dropping.

    I have also tried changing to a new scene calling:
    Code: Select all
    [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
    [[CCTextureCache sharedTextureCache] removeUnusedTextures];
    [[CCDirector sharedDirector] purgeCachedData];

    and returning to the MapScene. Still the memory increases by about 4MB when returning to the MapScene. The below textures are removed. None of which seem to be the TMX tileset texture file.
    Code: Select all
    cocos2d: CCTextureCache: removing unused texture: Veda_Down_4.png
    cocos2d: CCTextureCache: removing unused texture: NoButton.png
    cocos2d: CCTextureCache: removing unused texture: Veda_Down_5.png
    cocos2d: CCTextureCache: removing unused texture: MessageFont.png
    cocos2d: CCTextureCache: removing unused texture: MessageArrow_1.png
    cocos2d: CCTextureCache: removing unused texture: MessageCorner_1.png
    cocos2d: CCTextureCache: removing unused texture: Veda_Up_4.png
    cocos2d: CCTextureCache: removing unused texture: MessageVStrip_1.png
    cocos2d: CCTextureCache: removing unused texture: MessageSquare_1.png
    cocos2d: CCTextureCache: removing unused texture: MessageFill.png
    cocos2d: CCTextureCache: removing unused texture: YesButton.png
    cocos2d: CCTextureCache: removing unused texture: MessageHStrip_1.png
    cocos2d: CCTextureCache: removing unused texture: WhitePixel.png
    cocos2d: CCTextureCache: removing unused texture: Default.png
    cocos2d: CCTextureCache: removing unused texture: BlackPixel.png

    Below is the code I use to initialize the TMX map and Events:
    Code: Select all
    eventObjects = [[CCArray alloc] init];

    // Init Nodes     
    CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:aMap];
    [self addChild:map z:1 tag:1];

    // Initialize Event Objects
            CCTMXObjectGroup *npcMapObjects = [map objectGroupNamed:@"NPCs"];
            for (NSMutableDictionary *npc in npcMapObjects.objects) {           
                Event *npcObject = [[Event alloc] initWithEvents:npc map:map parent:self];
                [npcObject setScale:scaleFactor];
                int uniqueID = [[npc valueForKey:@"ID"] intValue];
                [self addChild:npcObject z:300 tag:100+uniqueID];
                [eventObjects addObject:npcObject];

    In the Event class, I allocate a few CCArrays and I add SpriteFrames to some CCAnimations.
    I have tried setting these to nil in case ARC was not releasing them properly upon cleanup or they weren't being cleaned up by the parent.

    Additional Information:
    - I am Using XCode 5 with iOS7
    - I am using an ARC setup from the following tutorial:
    - I am Testing on an iPhone 4S device
    - I have checked for leaks using Instruments

    Below are screenshots of the Memory Jumps in XCode and Instruments:

    As you can see the memory is Staircasing up. Each step occurs when I replace the scene with MapScene on the same or any map. In these tests, the TMX map and tileset are the same, yet the memory continues to grow. Only after about the tenth scene replacement, does a leak show up. In which case it seems that almost everything is leaking. Many leaks seem to be associated with TMX maps, CCSpriteFrames, and CCAnimations. I'm confused as I thought changing scenes would release memory for these objects automatically and ARC would handle the other objects that I specifically alocated.

    Do I need to manually remove all objects from CCArrays and make pointers to CC-objects nil upon cleanup?

    Any help would be greatly appreciated!
    - Jaron Lowe

Other Items of Interest Weekly

Sign up to receive the latest tutorials from each week, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Unity Starter Kit!

We are considering writing a new starter kit on making a game in C# with Unity.

Would this be something you'd be interested in, and if so which option would you prefer?

    Loading ... Loading ...

Our Books

Our Team

Video Team

... 12 total!

Swift Team

... 13 total!

iOS Team

... 52 total!

Android Team

... 9 total!

OS X Team

... 11 total!

Sprite Kit Team

... 10 total!

Unity Team

... 9 total!

Articles Team

... 11 total!