Objective-C言語のメモ書き(7)

2010. 03. 16
●オブジェクトの管理

・参照カウンタによるオブジェクトの管理

メモリの管理において、Objective-C 2.0で採用されたガベージコレクションはiPhone OSでは使えないというのは有名な話ですが、その辺も含めて整理したいと思います。

iPhoneやiPod touchは128MB~256MBと、昨今のPCと比べてかなり少ないメモリで動作させています。

その為メモリの管理にはPC以上に厳密な管理が必要になります。

PCだったら適当でいいと言う話ではありませんが、限られたリソースを有効に使うという意味で、必要最低限なメモリだけ確保し不要なオブジェクトは即解放する必要があります。

同時に不要になったオブジェクトがいつまでも解放されず、メモリ領域を確保し続けるメモリリークにも注意を払わなければなりません。

また、解放したオブジェクトにアクセスするようなことがあってはならないので、メモリ管理はかなり面倒な話です。

さて、Objective-C 2.0においては、メモリ管理として

・リファレンスカウンタ(または参照カウンタ)方式
・ガベージコレクション(またはガーベジコレクション)方式

の2種類があります。

ガベージコレクションは、不要になった(参照されない)メモリ領域を自動で解放してくれる便利な機能なのですが、本来のアプリケーションプログラムとは別個に、不要なオブジェクトを検索するプログラムを走らせる必要があります。

ガベージコレクションの処理は負荷が大きく、CPUパワーが非力で、急に電話がかかってきた場合などの即応性が求められることから、iPhone OSでは採用が見送られました。

従って、iPhone OSではリファレンスカウンタ方式でメモリを管理することになります。

・オブジェクト管理のためのメソッド

Objective-C言語のメモ書き(1)でも触れていますが、リファレンスカウンタはインスタンスオブジェクトのメモリを管理するものです。

参照カウンタとも呼ばれる通り、インスタンスに対して参照していることを示すフラグのようなものです。

allocでインスタンスを生成すると、リファレンスカウンタは1になります。

リファレンスカウンタは、retainメソッドを送ると1増え、releaseメソッドで1減り、0になるとdeallocメソッドが自動的に送られてメモリが解放されます。
(deallocを直接呼び出してはいけません)

つまり、正しく解放を行うにはリファレンスカウンタの数を把握していなければならず、インスタンスを保持したいからといって無闇にretainを送ると、解放できなくなる可能性があります。

現在のリファレンスカウンタ数は- (NSUInteger)retainCountメソッドで得られます。

NSLog(@"%d" , [インスタンス名 retainCount]);

●自動解放

複数のオブジェクトから参照するなど一定期間保持する必要が無く、一時的に呼び出した後はすぐに解放して構わない場合は- (id)autoreleaseメソッドが利用できます。

インスタンス名 = [[[クラス名 alloc] init] autorelease];

インスタンスの生成、初期化時にautoreleaseを加えれば、releaseメソッドを記述する必要が無くなり、インスタンス内の処理が終われば自動でメモリが解放されます。

●2種類のインスタンス化の方法

インスタンス化を行う際、同じようなメソッドでも

・- init~で始まるインスタンスメソッド
・+ で始まるクラスメソッド

の2種類があります。

- init~で始まるインスタンスメソッドは初期化メソッドと呼ばれるもので、allocで生成した後に呼び出し、初期化時にリファレンスカウンタが自動で+1されます。

この場合、使い終わったらreleaseメソッドで解放する必要があります。

一方、+ で始まるクラスメソッドは、生成も行うことからallocメソッドを書く必要がなく、初期化後自動解放されます。

●自動解放の功罪

一見便利な自動解放ですが、その実体はNSAutoreleasePoolオブジェクトによって実現されています。

テンプレートからプロジェクトを生成すると、Other Sources下のmain.mでNSAutoreleasePoolオブジェクトが生成され、自動解放のインスタンスはここに格納されることになります。

しかしNSAutoreleasePoolオブジェクトが解放されるのはアプリケーションの終了時で、アプリケーション終了まで自動解放のインスタンスはメモリ上に居座ることになり、多用すると容易にメモリを圧迫することが予想されます。

小規模のアプリケーションなら問題は出難いと思いますが、基本的には手を抜かずに手動解放した方が望ましいようです。

※2010.4.17訂正
24/7 twenty-four seven/autoreleaseされたオブジェクトはいつ解放されるか』によりますと、

NSAutoreleasePoolはイベントループが一周するたびに生成と破棄を繰り返します。ですので、アプリケーション終了まで、オブジェクトが溜まっていくということはありません。たいていは、autorelease済みのオブジェクトはメソッドを抜けた後に解放されます。

ということでした。お詫びして訂正させていただきます。



参考文献

混沌のiPhoneアプリケーション工房/プログラミング/メモリ管理

混沌のiPhone開発ブログ/iPhoneアプリケーション開発でautoreleaseが非推奨の理由

A Day In The Life/iPhoneアプリ開発時のメモリ管理で気をつけること

iPhone SDK 3 プログラミング大全 実践プログラミング (MacPeople Books)iPhone SDK 3 プログラミング大全 実践プログラミング (MacPeople Books)
(2009/09/08)
木下 誠

商品詳細を見る

詳解 Objective-C 2.0 第3版詳解 Objective-C 2.0 第3版
(2011/12/28)
荻原 剛志

商品詳細を見る






Bose QuietComfort 20
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
08 | 2017/09 | 10
Sun Mon Tue Wed Thu Fri Sat
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

Bose QuietComfort 20
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR