본문 바로가기

General/iOS

[iPhone] 메모리 관리



안드로이드 어플리케이션과 비교해서, 아이폰 어플리케이션은 개발자가 직접 메모리 관리를 해주어야 합니다.
그래서 개발자는 오브젝트의 라이프 사이클을 항상 염두에 두어야 합니다.


 Object Lifecycle
- Creating objects
- Memory management
- Destroying objects


아래는 Creating objects부터 destroying objects 까지 입니다.
나눠놨지만, 사실상 연속적으로 일어나는 일들인지라, 겹치는 내용들이 존재합니다.





Creating objects

Object create
- alloc : Class method that knows how much memory is needed.
- init : 초기값을 설정하거나 다른것들을 설정하는 인스턴스 메소드
Create = Allocate + Initialize


Implementation your own -init method
- init메소드를 자체적으로 구현할 수 있습니다. 실제로 많이 쓰입니다.
@implementation OBJECT

-(id)init 
{ // allow superclass to initialize its state first
    if ( self = [super init] 
    {
     ... 
     }
 ...
}

@end 







Memory management

   Allocation  Destruction
 C  malloc  free
 Objective-C  alloc  dealloc

allocation과 destruction의 균형잡힌 호출이 필요하다.
(그렇지 않다면 memory leak이나 crash가 발생한다.)
그러나! -dealloc 을 직접적으로 호출해서 쓰지는 못한다. 
그렇기 때문에 Reference Counting을 한다.

Reference counting
모든 object는 retain count를 가진다. (NSObject에 정의되어 있다.)
 retain count > 0, object는 살아있는, 유효한 상태이다. 

+alloc 과 -copy는 object를 만들때, 1의 retain count를 준다. (retain += 1, 확인해야함)

-retain은 retain count를 증가 시킨다. (retain += 1)

- release는 retain count를 감소 시킨다. (retain -= 1)

retain count 가 0이 될 때, object는 destroy된다. (object is destroyed)

-dealloc method는 자동으로 실행된다.
(한번 -dealloc으로 날아가버린 것들은 다시 되돌릴 수 없다.)


Messaging deallocated objects
Person *person = [[Person alloc] init]; // ... 
[person release]; // Object is deallocated
[person doSomething]; // Crash!  

Person *person = [[Person alloc] init]; // ... 

[person release]; // Object is deallocated

person = nil; 
[person doSomething]; // No effect
 
 


Object Ownership

#import "Person.h"

@implementation Person


- (NSString *)name 

    return name;


- (void)setName:(NSString *)newName 

{

    if (name != newName) 

    { 

        [name release];

        name = [newName retain]; 

        // name’s retain count has been bumped up by 1

    }
}

@end
 

#import "Person.h"

@implementation Person


- (NSString *)name 

    return name;


- (void)setName:(NSString *)newName 

{

    if (name != newName) 

    { 

        [name release];

        name = [newName copy]; 

        // name has retain count of 1, we own it

    }

}

@end  








Destroying objects

Releasing Instance Variables

#import "Person.h"


@implementation Person


- (void)dealloc 

{

    // Do any cleanup that’s necessary

    [name release];

    // when we’re done, call super to clean us up 

    [super dealloc];


@end


Implementation your own -dealloc method : dealloc method 구현

#import "Person.h"


@implementation Person


- (void)dealloc 

    // Do any cleanup that’s necessary // ...

} 

@end
 



Autoreleasing Objects

: -autorelease flag를 불러서 오브젝트의 미래 어떤 시점에 release를 보내 놓습니다.

: object가 살아있는 동안 가지는 retain/release의 의무를 수행할 수 있게 해줍니다.

: 메모리 관리를 편하게 더 편하게 할 수 있습니다.

: 새롭게 생성된 object를 return하는 아주 유용한 메소드입니다.

- (NSString *)fullName 

    NSString *result;

    result = [[NSString alloc] initWithFormat:@“%@ %@”,                 firstName, lastName];

    [result release]; 

    

    return result;

}
// Wrong : result is released too early!
// Method returns bogus value

- (NSString *)fullName 

    NSString *result;

    result = [[NSString alloc] initWithFormat:@“%@ %@”, 

              firstName, lastName];

    [result autorelease]; 

    return result;

}

// Just right : result is released!!
// but not right away Caller gets valid object and could retain if needed



Autorelease을 가진 method names : 래스 메소드처럼 보이는 것들

NSMutableString *string = [[NSMutableString alloc] init];

// We are responsible 

// for calling -release or -autorelease

[string autorelease];

NSMutableString *string = [NSMutableString string];

// The method name doesn’t indicate that we need to release it // So don’t- we’re cool!



Autorelease Pools