AS3 to Objective-C : Memory Management

As Flash and Flex developers,we’re no strangers to the concept of file optimization, and when developing for the iPhone most of the same rules apply: keep your images as small as possible, reuse wherever you can get away with it, etc., but the focus or the goal is different.
Another important concept that Objective-C introduces for ActionScript developers is that of pointers. A variable represents a value stored in memory where a pointer represents an address in memory where a value exists. Primitive types in Objective-C can be declared as either variables or pointers, but all objects must be declared as pointers. To declare a pointer you use an asterisk in your declaration, so: int myInt; declared as a pointer would be int *myIntPtr;. The asterisk doesn’t hav to be next to the pointer name, it can be with the pointer type or in between the two. In other words, these are all legal pointer declarations:
[code lang="objc"]int *myIntPtr;
int* myIntPtr;
int * myIntPtr;[/code]
To get the address of a variable, you use the ampersand, so given the variable int myInt; the address of myInt would be given by &myInt. So you can declare that int *myIntPtr = &myInt;. I can illustrate this with an example:
[code lang="objc"]int myInt = 100;
int *myIntPtr = &myInt;
int myIntCpy = *myIntPtr;
NSLog(@"myInt: %i", myInt); //myInt: 100
NSLog(@"&myInt: %i", &myInt); //&myInt: -1073748556
NSLog(@"myIntPtr: %i", myIntPtr); //myIntPtr: -1073748556
NSLog(@"myIntCpy: %i", myIntCpy); //myIntCpy: 100[/code]
Because *myIntPtr points to the value stored for myInt, any changes made to *myIntPtr will change myInt, so:
[code lang="objc"]int myInt = 100;
NSLog(@"myInt = %i", myInt); //myInt = 100
int *myIntPtr = &myInt;
*myIntPtr *= *myIntPtr;
NSLog(@"myInt = %i", myInt) //myInt = 10000[/code]
When working with objects, you allocate a chunk of memory for the object to use and your pointer points to this memory. To do this, you invoke a class function inherited from the NSObject class: +alloc. This does not call the constructor for your object, it simple grabs enough memory for the object to use. The constructor function is called -init, but many objects have several different init functions, so make sure to read the help docs to find the one that works best for your use. To initialize an NSString object, for example you could:
[code lang="objc"]NSString *myString = [[NSString alloc] initWithString: @"This is a string"];[/code]
Allocating memory is an expensive process – this means that it uses a fair bit of the CPU to do this (like creating MovieClips in ActionScript) so you want to do this as little as possible. On the iPhone reducing CPU load not only makes your app run smoothly, it also reduces the drain on the battery. What you’ll want to do to avoid this is hold on to any values that get reused often. It is also important, with objects, because you have allocated a chunk of memory for their use that you want to release that memory when you no longer need it. You also want to make sure that you don’t lose your reference to that allocated memory – once you lose that reference you can’t get it back. This is called a memory leak and they will eventually crash your app and in extreme cases can affect the general stability of the phone itself (until you reboot, of course). To release an object once you have finished with is, you call the object’s -release function:
[code lang="objc"]NSString *myString = [[NSString alloc] initWithString: @"This is a string"];
...
[myString release];[/code]
When deploying for web, you want to keep quality as high as possible while keeping your file size as small as possible. On the iPhone you have 8 or 16GB of space, so file size isn’t as much of a concern as memory use is. The iPhone has 128MB of memory onboard (of which you’re lucky to have 20MB for your own use) and doesn’t use a swap file for additional memory so once you’re out, that’s it – you don’t get any more. On the flip side, when deploying for web you’re typically dealing with computers that have hundreds of MBs of available memory and can write to a swap file. To deal with this, the iPhone generates memory warnings which get sent to view controllers via the -didReceiveMemoryWarning function. Responding to memory warnings is completely optional, but if your app does try to grab too much memory it will trigger a warning and if you don’t respond to it, your app will close.
As someone coming from an ActionScript development background this brought a new way of thinking about how I write my code. I now want to be able to write code so that, if I receive a warning, I can release everything I don’t absolutely need right now in order to keep my app functioning. The solution at first sounds simple: get rid of everything as soon as you’re done with it. The problem with this approach is that allocating memory is more expensive (in terms of CPU use) than retaining memory and if you make the CPU work less, you conserve battery life. So instead of releasing everything immediately, you want to retain your object, whenever you access them make sure they exist and when you receive a memory warning you want to make sure you release everything you don’t absolutely need.




very helpful ideas! we’re making the same conversion from Flash…
-V
[...] http://blog.teknision.com/?p=164 [...]