5. iOS Memory Management
ObjectiveC objects contain a ‘count’ of how many
other objects are currently holding onto them.
You increment that count with the retain message.
You decrement that count with the release message.
When that count hits 0.
The object is deallocated from memory
14. iOS Memory Management
Releasing an object
Release an object by sending it the release message
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:@"UPLeaderboardViewCell"
owner:nil options:nil];
NSMutableArray *mutableTopLevelObjects = [topLevelObjects mutableCopy];
[mutableTopLevelObjects release];
15. iOS Memory Management
Releasing an object
Release an object by sending it the release message
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:@"UPLeaderboardViewCell"
owner:nil options:nil];
NSMutableArray *mutableTopLevelObjects = [topLevelObjects mutableCopy];
[mutableTopLevelObjects release];
Releasing an object doesn’t remove it from memory.
It simply decrements the objects retainCount by 1.
When an objects retainCount is equal to 0.
The object is deallocated by the runtime automatically.
16. iOS Memory Management
Releasing an object
Release an object by sending it the release message
NSMutableArray *mutableTopLevelObjects = [topLevelObjects mutableCopy];
[topLevelObjects retainCount]; // => 1
[topLevelObjects retain];
[topLevelObjects retainCount]; // => 2
[mutableTopLevelObjects release];
[topLevelObjects retainCount]; // => 1
[topLevelObjects release];
[topLevelObjects retainCount]; // => 0
Releasing an object doesn’t remove it from memory.
It simply decrements the objects retainCount by 1.
When an objects retainCount is equal to 0.
The object is deallocated by the runtime automatically.
18. iOS Memory Management
So what about the other objects?
They’re what’s known as autorelease objects.
19. iOS Memory Management
So what about the other objects?
They’re what’s known as autorelease objects.
// This object will be automatically released at some point
// in the future when the autorelease pool is drained
NSString *aString = [NSString stringWithFormat:@"a string with an int %i", 1];
20. iOS Memory Management
So what about the other objects?
They’re what’s known as autorelease objects.
// This object will be automatically released at some point
// in the future when the autorelease pool is drained
NSString *aString = [NSString stringWithFormat:@"a string with an int %i", 1];
You can mark your own objects as autorelease objects
21. iOS Memory Management
So what about the other objects?
They’re what’s known as autorelease objects.
// This object will be automatically released at some point
// in the future when the autorelease pool is drained
NSString *aString = [NSString stringWithFormat:@"a string with an int %i", 1];
You can mark your own objects as autorelease objects
[topLevelObjects retainCount]; // => 1
[topLevelObjects autorelease];
[topLevelObjects retainCount]; // => 1 since it will be released later
22. iOS Memory Management
NSAutoreleasePool
“Cocoa always expects there to be an autorelease pool available”
- Memory Management Programming Guide: Autorelease Pools
// main.m
// The main entry point into the app sets up
// an autorelease pool for us automatically
int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
24. iOS Memory Management
Common mistakes
// You need to mark zero for autorelease or release it
- (void)reset {
NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
[self setCount:zero];
}
25. iOS Memory Management
Common mistakes
// You need to mark zero for autorelease or release it
- (void)reset {
NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
[self setCount:zero];
}
// zero is an autorelease object already.
// you haven't used alloc/copy anywhere
// you are over releasing the zero object
- (void)reset {
NSNumber *zero = [NSNumber numberWithInteger:0];
[self setCount:zero];
[zero release];
}
26. iOS Memory Management
Common confusion
// Adding an object to a collection retains the object
// It transfers ownership to the parent collection
// Since alloc/copy was never called you don’t need
// to release convenienceNumber
NSMutableArray *array = [[NSMutableArray alloc] init];
NSUInteger i = 0;
for (i; i < 10; i++) {
NSNumber *convenienceNumber = [NSNumber numberWithInteger:i];
[array addObject:convenienceNumber];
}
27. iOS Memory Management
Common confusion
// Adding an object to a collection retains the object
// It transfers ownership to the parent collection
// You need to release allocedNumber here since you alloced it.
NSMutableArray *array = [[NSMutableArray alloc] init];
NSUInteger i = 0;
for (i; i < 10; i++) {
NSNumber *allocedNumber = [[NSNumber alloc] initWithInteger: i];
[array addObject:allocedNumber];
[allocedNumber release];
}
29. iOS Memory Management
Returning Objects from Methods
// Correct - You don't own the string object so you should return it as such.
- (NSString *)fullName {
NSString *string = [NSString stringWithFormat:@"%@ %@",
self.firstName, self.lastName];
return string;
}
30. iOS Memory Management
Returning Objects from Methods
// Correct - You don't own the string object so you should return it as such.
- (NSString *)fullName {
NSString *string = [NSString stringWithFormat:@"%@ %@",
self.firstName, self.lastName];
return string;
}
// Incorrect - You're returning an object that has already been released.
- (NSString *)fullName {
NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",
self.firstName, self.lastName]
release];
return string;
}
31. iOS Memory Management
Returning Objects from Methods
// Correct - You don't own the string object so you should return it as such.
- (NSString *)fullName {
NSString *string = [NSString stringWithFormat:@"%@ %@",
self.firstName, self.lastName];
return string;
}
// Incorrect - You're returning an object that has already been released.
- (NSString *)fullName {
NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",
self.firstName, self.lastName]
release];
return string;
}
// Correct - You've created an autorelease object.
- (NSString *)fullName {
NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",
self.firstName, self.lastName]
autorelease];
return string;
}
35. iOS Memory Management
Accessor Method - @property/@synthesize
// MyClass.h
// Will retain the variable sent to it.
@property(nonatomic, readwrite, retain) NSString *myString;
// Will not retain the variable sent to it.
@property(nonatomic, readwrite, assign) NSString *myWeakString;
36. iOS Memory Management
Accessor Method - @property/@synthesize
// MyClass.m
// Will retain the variable sent to it.
@synthesize myString = _myString;
// The @synthesize produces a setter/getter combo(readwrite)
-(NSString *)myString
{
return _myString;
}
-(void)setMyString:(NSString *)myString
{
if (myString != _myString)
{
[_myString release];
_myString = [myString retain];
}
}
37. iOS Memory Management
Accessor Method - @property/@synthesize
// MyClass.m
// Will not retain the variable sent to it.
@synthesize myWeakString = _myWeakString;
// The @synthesize produces a setter/getter combo(readwrite)
-(NSString *)myWeakString
{
return _myWeakString;
}
-(void)setMyWeakString:(NSString *)myWeakString
{
_myWeakString = myWeakString;
}
38. iOS Memory Management
Accessor Methods - @property/@synthesize
// MyClass.m
// By synthesizing in this way you are protecting your iVar so it can
// only be accessed through the setter.
// It also means you can pass the argument myString to methods.
@synthesize myString = _myString;
-(id)initWithMyString:(NSString *)myString
{
if ((self = [super init]))
{
self.myString = myString;
}
return self;
}
+(id)myClassWithMyString:(NSString *)myString
{
return [[self initWithMyString:myString] autorelease];
}
39. iOS Memory Management
Accessor Methods - @property/@synthesize
// MyClass.m
// By synthesizing in this way you are protecting your iVar so it can
// only be accessed through the setter.
// It also means you can pass the argument myString to methods.
@synthesize myString;
-(id)initWithMyString:(NSString *)cantBeCalledMyStringNow
{
if ((self = [super init]))
{
// Woops I assigned straight to the iVar. So it’s not retained now
myString = cantBeCalledMyStringNow;
}
return self;
}
+(id)myClassWithMyString:(NSString *)cantBeCalledMyStringNow
{
return [[self initWithMyString: cantBeCalledMyStringNow] autorelease];
}