2010年7月18日 星期日

[IPhone] Memory management with UIView

Introduction
Memory management in the Iphone is a hot topic.
I might as well share some tips here from my own experience.

Background
I got a game project of iphone at the end of March, 2010.
Then I started to study development in Iphone with Object-C and C++.
I developed a library that named CloudBox and used to develop my project of game.
In the past, I had met many times of crash, the reason was issue of memory management.

Sample 1

    UIImage *tmp = [UIImage imageNamed:@"logo.png"]; // imageNamed will return an autorelease object
bigpicture = [[UIImageView alloc] initWithImage:tmp];
//[tmp release];
// if you release a autorelease object, you application may be crash.
// so it dose not need release
Avoid using autorelease object.
If you use an autorelease object, you can not control when it was released.
And if you release an autorelease object by yourself, sometimes might cause crash.
[NSxxx xxxGenerate] naming function will return an autorelease object, like [UIImage imageNamed] or [NSString stringWithFormat].

Sample 2

class SuccessView
{
private:
UIImageView* m_View;
public:
SuccessView(UIView* parentView);
~SuccessView();
};

SuccessView::SuccessView(UIView* parentView)
{
m_View = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
// after alloc, m_View's retainCount = 1
[parentView addSubView:m_View];
// after addSubView, m_View's retainCount = 2
}

SuccessView::~SuccessView()
{
[m_View removeFromSuperview];
// after removeFromSuperview, m_View's retainCount = 1
[m_View release];
// after release, m_View's retainCount = 0, release success.
}

class CrashView
{
private:
UIImageView* m_View;
public:
CrashView(UIView* parentView);
~CrashView();
};

CrashView::CrashView(UIView* parentView)
{
m_View = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
// after alloc, m_View's retainCount = 1
[parentView addSubView:m_View];
// after addSubView, m_View's retainCount = 2
[m_View release];
// after release, m_View's retainCount = 1
}

CrashView::~CrashView()
{
[m_View release];
// this release may cause application crash.
}

class DemoSample
{
private:
UIView* m_MainView;
SuccessView* success;
CrashView* crash;
public:
DemoSample();
~DemoSample();

void TestRemoveSuccessView();
void TestRemoveCrashView();
};

DemoSample::DemoSample()
{
m_MainView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
success = new SuccessView(m_MainView); // draw success view on m_MainView
crash = new CrashView(m_MainView); // draw crash view on m_MainView
}

DemoSample::~DemoSample()
{
[m_MainView release];
}

void DemoSample::TestRemoveSuccessView()
{
delete success; // it will success to remove this view from m_MainView
}
void DemoSample::TestRemoveCrashView()
{
delete crash; // it will cause crash
}
In develop of game, I used random generate NPC.
If NPC dead, I will remove NPC on screen and release it.
In the past, I got a experience.
When I release UIImageView without removeFromSuperview, the application will crash.
I got some conclusions:
1. view = [UIImageView alloc] => view's retainCount = 1
2. [parentView addSubview:view] => view's retainCount = 2
3. [view removeFromSuperview] => view's retainCount = 1
4. [view release] => view's retainCount = 0

Reference
IPhone Memory Management
IPhone Memory Management Tips
Apple Document

沒有留言:

張貼留言

Hello