SlideShare a Scribd company logo
1 of 67
Download to read offline
第6回iPhone輪講
Lesson12~
Big Waveに乗った人の図
Lesson12
メモリ管理
メモリ管理
メモリの確保と解放
アプリケーションを起動したり,ウィンドウを開いたり,コンピュータは
何をするにもメモリが必要
これらの作業において,いつメモリが必要になるのか突き詰めて行くと
オブジェクトをインスタンス化したときということになる
オブジェクトをインスタンス化するということは,そのオブジェクトが
必要な量のメモリを確保するという事
メモリ管理
メモリの確保と解放
メモリの量は有限なので確保し続けたらいつかはなくなる
そこで必要なくなったメモリは解放しなくてはいけない
これでそのメモリは別のところで再利用できる
メモリにまつわる問題
メモリ解放のタイミング
メモリは確保するときは特に問題ない
必要なときに必要なだけ確保すればよい
問題は解放のとき
原則的には必要なくなったときに解放すればよい
しかし,いつ必要なくなったかわかるのか?
メモリにまつわる問題
メモリ解放のタイミング
ウィンドウ上のボタンにタイトルを設定するとする
タイトルは文字列なので,まず文字列のためのメモリを
確保し,タイトルを設定する
このメモリはいつ解放すればいいのか?
ボタンに設定したすぐ後なのか?
この段階ではボタンがこの文字列オブジェクトを使ってい
るかもしれないので,まだ解放できない
メモリにまつわるの問題
メモリの解放のタイミング
ボタン自体が解放されるときなら確実
そうなるとボタンが解放されるまで見張り続けなければいけない
確保したオブジェクトを自分だけが使っていれば,いつ解放すればいいか
自分で決められるのでそれほど問題ではない
メモリリーク
もしメモリの解放を忘れた場合どうなるのか
そのメモリはアプリケーションが終了するまでずっと占領されてしまう
それが何度も繰り返して起こると,搭載されているメモリの量を
超えてしまい,再起動しなければならない状態になる
この問題をメモリリークと呼ぶ
ガベージコレクションによるメモリ管理
ガベージコレクション(Garbage Collection)とは
何か?
メモリ上の使われなくなったオブジェクトをゴミとみなして定期的に
それを回収し,メモリ領域を再利用できるようにする
どのように,あるオブジェクトがゴミかそうでないかを
見分けるのかが問題
ガベージコレクションによるメモリ管理
ゴミでない(まだ使われている)オブジェクトを
考える
あるオブジェクトが使われている
→他のオブジェクトがそのオブジェクトを必要としている
オブジェクトを必要としていることがプログラム中でどうなるのかという
と,そのオブジェクトを参照しているということ
つまりインスタンス変数として参照をキープしている
ガベージコレクションによるメモリ管理
ゴミでない(まだ使われている)オブジェクトを
考える
あるオブジェクトが使われている
→他のオブジェクトがそのオブジェクトを必要としている
オブジェクトを必要としていることがプログラム中でどうなるのかという
と,そのオブジェクトを参照しているということ
つまりインスタンス変数として参照をキープしている
ゴミとなるオブジェクトは「誰からも
参照されていないオブジェクトのこと」
と,言い切れるものではない
ガベージコレクションによるメモリ管理
A
B C
D E
次のような状況が考えられる
いま5つのオブジェクトがある
Aは必要なオブジェクトでB,Cを参照している
従ってBとCはゴミではない
DとEはゴミだが,互いに参照している
「参照されていないオブジェクトがゴミ」という
ルールだとDとEをゴミとして認識する事ができない
オブジェクトの参照だけでは
ゴミか決定できない
ガベージコレクションによるメモリ管理
これを解決するには「必要なオブジェク
ト」を決める必要がある
そこから参照されているオブジェクトはゴミでないとする
すべての必要となるオブジェクトの参照を辿った後,
まだ必要とされてないオブジェクトをゴミとする
これがガベージコレクションのゴミ回収ルールである
このような絶対に必要なオブジェクトは
「ルートオブジェクト」と呼ばれる
A
B C
D E
ルートオブジェクト
(NSApplication)
A,B,Cは必要なオブジェクト
D,Eはゴミ
ガベージコレクションによるメモリ管理
Cocoaの場合のルートオブジェクトは何か
まずアプリケーションそのものを表すオブジェクト
これは「NSApplication」というクラスのインスタンスになる
またメソッドやクラスの外で宣言しているオブジェクトも
必要なものになる
ガベージコレクションによるメモリ管理
このゴミ決定ルールを使う事での
ガベージコレクションの挙動
1.まずアプリケーションが起動する
2.しばらく好き勝手にオブジェクトを作り,できたものは放っておく
3.ある程度の量のオブジェクトを作ったら,一旦アプリケーションの実行を
停止し,ガベージコレクションを発動する
ガベージコレクションによるメモリ管理
このゴミ決定ルールを使う事での
ガベージコレクションの挙動
4.ガベージコレクションでは,すべてのルートオブジェクトから参照を辿って行
き,必要とされるオブジェクトにマークをつける
5.最後までマークがつかなかったオブジェクトをゴミと見なし,回収して解放
する
6.使用可能なメモリ領域が広がったところでアプリケーション実行の再開
ガベージコレクション
ガベージコレクション有効化
ガベージコレクションは標準では無効化されているので有効化する
Xcodeで適当なプロジェクトを開く
[プロジェクト]→ [プロジェクト設定を編集]メニューを選択
プロジェクト情報パネルが開く
ガベージコレクション
ガベージコレクションの有効化
情報パネルの左から2番目「ビルド」のタブを選択
ここでビルドの設定ができる
「Objective-C Garbage Collection」という項目を探す
見つかったら値の設定をする
値はUnsupported,Supported,Requiredの3種類
ガベージコレクションの設定
Unsupported
ガベージコレクションを無効化する
Supported
主にプラグインを利用するために用意された項目
アプリケーションの本体がガベージコレクションに対応していても,
プラグインが対応しているかわからない
ガベージコレクションに対応していないプラグインでも読み込ん
で,実行できるようにする
ガベージコレクションの有効化
ガベージコレクションの設定
Required
すべてコードがガベージコレクション対応のものとして扱う
自分で通常のアプリケーションを作る場合はこれを選択する
ガベージコレクションの有効化
参照カウンタ
参照カウンタ
メモリ管理の手法としていろいろなフレームワークで使われているもの
基本的な考え方は,あるオブジェクトに対して,それが必要なら必要な人が
つばをつけておく
必要なければ「要らない」と宣言しておく
参照カウンタ
参照カウンタ
誰からも必要とされなくなったら,オブジェクトは解放される
このときのつばを付ける事を,オブジェクトを参照する(refer)
または,保持する(retain)と呼ぶ
参照された回数を数えて管理するので,参照カウンタと呼ばれる
retain,releaseメソッド
参照カウンタの手法では2つの操作が基本となる
オブジェクトを参照するための操作
参照をやめるための操作
Cocoaではこれらの操作に対応するメソッドが用意してある
参照するために使うのはretain
参照をやめるために使うのはrelease
これらはルートオブジェクトであるNSObjectのメソッド
オブジェクトの確保から解放までの流れ
retainとreleaseでオブジェクトの確保から解放ま
でが,どのように管理されているかの流れ
AppControllerがボタンにタイトルを設定するという処理
オブジェクトの確保から解放までの流れ
確保から解放までの流れ1
AppControllerは,タイトルを表す文字列オブジェクトを作る
このとき文字列オブジェクトの参照カウンタは1である
インスタンス化されたオブジェクトの参照カウンタの初期値は1になる
0だった場合,いきなり解放される
AppController
@ Push Me!
インスタンス作成
参照カウンタ=1
オブジェクトの確保から解放までの流れ
確保から解放までの流れ2
AppControllerは setTitle:といったメソッドを使い
ボタンにタイトルを設定する
ボタンはメソッドの中で,この文字列オブジェクトはまだ必要だと
判断してretainメソッドを呼び出す
これで参照カウンタは1つ増えて2になる
ボタンではこのオブジェクトを指し示すための変数をキープしてく必要が
ある
AppController @ Push Me!
タイトル設定
ratain
参照カウンタ=2
Push Me!
オブジェクトの確保から解放までの流れ
確保から解放までの流れ3
AppControllerからすると,このオブジェクトはもう必要ない
そこでreleaseメソッドを呼び出し参照をやめる
参照カウンタは1減って1となる
これ以降AppController側では文字列オブジェクトのための
変数を捨ててしまってもかまわない
AppController @ Push Me!
release
参照カウンタ=1
Push Me!
オブジェクトの確保から解放までの流れ
確保から解放までの流れ4
ある程度処理が進み,ユーザがウィンドウを閉じたとする
ウィンドウ上のボタンも解放される
ボタンは解放されるとき自分が参照していた文字列オブジェクトに対して
必要なくなるのでreleaseメソッドを呼び出す
参照カウンタが0になるので,文字列オブジェクトは解放される
@ Push Me!
参照カウンタ=0
Push Me!
release
クラスのインスタンス化
クラスのインスタンス化と初期化
クラスのインスタンス化をおこなうメソッドはalloc
これを呼ぶ事でインスタンス化(オブジェクトのためのメモリ確保)が
行われる
allocはクラスメソッド
インスタンス化したいクラス名を指定してallocを呼ぶことになる
クラスのインスタンス化
クラスのインスタンス化と初期化
allocでインスタンス化したら,必ず初期化をしなくてはならない
インスタンス変数の値の初期値の設定や,その他インスタンスを
使う前にやる必要がある処理を行ってくれる
初期化するには初期化メソッドを呼ぶ
初期化メソッドはクラスごとに用意されており,どれか適切なものを
選ぶ事になる
NSObject
+ (id) alloc
クラスをインスタンス化します.返り値はそのインスタンスオブジェクトになります.
クラスのインスタンス化
クラスのインスタンス化と初期化
initという一番基本的な初期化メソッドがある
NSObjectが持っているメソッドで,特別な初期化メソッドを呼ぶ必要
がないときはこれを呼ぶ
NSObject
- (id) initi
インスタンスを初期化します
クラスのインスタンス化
クラスのインスタンス化と初期化
インスタンス化の基本はallocとinitを続けて呼ぶ事
MyObjectというクラスのインスタンス化の例
[[クラス�alloc] init]と重ねて呼ぶのがインスタンス化の
基本のひとつ
このように初期化すると,参照カウンタは1となる
誰かがreleaseを呼ばない限り解放されない
クラスのインスタンス化
自動解放
一時的に作ったにすぎないオブジェクトに自動的にreleaseを送るための
自動解放と呼ばれる仕組みが存在する
自動解放を使うと,その処理が終わった後,適切な場所で
releaseメソッドを呼んでくれる
自動解放を使うにはautoreleaseというメソッドを呼ぶ
クラスのインスタンス化
自動解放
MyObjectをインスタンス化して,さらに自動解放する例
[[[クラス名 alloc] init]autorelease]と3段重ねで呼ぶ
インスタンス化のときautoreleaseを呼ぶかは,そのオブジェク
トを一時的にしか使わないのか,しばらく使うのかで決定する
NSObject
- (id) autorelease
インスタンスを自動解放します.返り値として自分自身を返します.
インスタンスの解放
参照カウンタが0になると,そのインスタンスは
解放される
解放される直前にdeallocというメソッドが呼び出される
サブクラスでこのメソッドを上書きする事で,解放されるときに必要な処理
を行う事ができる
NSObject
- (void) dealloc
インスタンスが解放される直前に呼び出されます.
インスタンスの解放
deallocの主な仕事はインスタンス変数の解放
もしクラスの中でなんらかのインスタンスを保持していたら
ここで必ず解放する
そうでないとメモリリークが起きる
deallocの実装例
ここではdocumentというインスタンス変数のreleaseメソッドを呼び出し
ている
このようにインスタンス変数を解放している
メモリ管理の定石
一般的なオブジェクト
NSAutoreleasePool
自動解放はNSAutoreleasePoolというクラスによって実現されている
例えるのなら時限付きゴミ袋
一般的なオブジェクト
NSAutoreleasePool
自動解放をおこなうには,まずNSAutoreleasePoolのインスタンスを作る
その状態でautoreleaseメソッドを呼び出すと,そのインスタンスが
NSAutoreleasePoolに登録される
最後にNSAutoreleasePoolを解放すると,登録されているすべての
releaseメソッドを呼び出す
NSAutoreleasePoolによる
自動解放の実現
autorelease
release
NSAutoreleasePoolを
作成
autoreleaseを呼ぶと
NSAutoreleasePoolに追加
NSAutoreleasePoolが
解放されるとすべての
オブジェクトにreleaseを送る
NSAutoreleasePoolの
作成と解放のタイミング
自動解放を行うときNSAutorelesePoolの
インスタンスは誰がいつ用意するのか
Cocoaアプリケーションを立ち上げると,その内部でイベントループと
呼ばれるループが回る事になる
イベントループはユーザからのキーボード入力や,マウス操作を待ち受ける
ループのこと
マウスのクリックの通知がくると,ユーザインタフェースのどの部分がク
リックされたかを調べ,最終的に登録されたアクションを呼び出したりする
NSAutoreleasePoolの
作成と解放のタイミング
イベントループの頭でNSAutoreleasePoolのイン
スタンスを作成し,最後に解放している
イベントループの内部であれば,いつでも自動解放を使える
Cocoaのアプリケーションではほとんどの処理がInterface Builderで
登録したアクションをトリガーとして始まる
アクションはイベントループが呼び出されて実行が始まり,終わるとルー
プが一周する
アクション実行中は常にNSAutoreleasePoolのインスタンスがある
アクションメソッドが終わると自動解放されたオブジェクトは
解放される
アクションの呼び出しと
NSAutoreleasePool
イベントループ開始
NSAutoreleasePool作成
アクションメソッド実行
インスタンスを作成して自動解放すると
NSAutoreleasePoolに登録される
アクションメソッド終了
まだ自動解放されたインスタンスは
解放されない
NSAutoreleasePool解放
自動解放されたインスタンスは,
ここで解放される
メモリ管理の定石のまとめ
オブジェクトを保持するか,一時的に使うだけか
判断する
インスタンスを作るとき,または他で作られたオブジェクトをメソッドの引数
として受け取ったときは,そのオブジェクトが保持する必要があるのか,
一時的に使うだけかを判断する
そのメソッドの内部でしか使わないのか,メソッドが終了した後でも
何度も使うかの違い
メモリ管理の定石のまとめ
保持するオブジェクトは,参照カウンタを上げる
保持する必要があるオブジェクトに対しては参照カウンタを1つ上げておく
他からもらったオブジェクトの場合はretainメソッドを呼んでやる
自分でインスタンスを作成するときはalloc-initの組み合わせで作る
または,init...で始まる初期化メソッドを使う
忘れずにこのオブジェクトをインスタンス変数としてキープしておく
メモリ管理の定石のまとめ
一時的なオブジェクトは自動解放する
一時的にしか使わないオブジェクトは自動解放しておく
インスタンスの作成をalloc-init-releaseの3段重ねで行う
またはそれぞれのクラスで自動解放されたインスタンスを作成する
ためのメソッドを使う
メソッドの引数として渡された場合は特に何もする必要が無い
そのオブジェクトに対する責任は,それを作ったクラスが持つ事になる
メモリ管理の定石のまとめ
deallocですべて参照カウンタを下げる
保持しているオブジェクトは最後に解放しなくてはならない
それをおこうなうチャンスがdeallocメソッド
deallocメソッドを上書きして,保持しているインスタンス変数すべての
releaseメソッドを呼びだす
このとき保持されているオブジェクトがその場で解放されるかは
わからない
まだ別のオブジェクトから保持されている可能性がある
Lesson13
文字列
NSStringとNSMutableString
Cocoaの文字列クラスがNSStringと
NSMutableString
NSStringクラスは内容を変更しない固定の文字列を表す
NSMutableStringクラスは内容の変更できる可変の文字列である
NSObject
NSMutableString
NSString
NSStringとNSMutableString
NSString,NSMutableString
NSStirngは一度インスタンスを生成するとテキストを変更できない
ウィンドウやボタンのタイトルを取得するときのように,勝手に内容を
変更されたくないときに使う
文字列の追加や削除などの編集を行いたい場合はNSMutableString
を使う
NSMutableStringはNSStringを継承しているので,
NSStringに対して行える操作はすべて使える
文字列の作成
@ を使った作成
C言語ではダブルクォーテーション( )でくくることにより
文字列が作成できた
ダブルクォーテーションの前に@をつける事で,C言語の文字列
(charの配列)ではなくNSStringのインスタンスとなる
文字列の作成
日本語文字からの作成
NSStringの作成はアルファベットでしか使えないので,日本語文字列を
作る事ができない
しかしデバッグなどで日本語が使いたいときは,
C言語の文字列からNSStringのインスタンスを作るメソッド
stringWithCString:encoding:
または,initWithCString:encoding:を使う
文字列の作成
前者の方は自動解放されたインスタンスを作成する
後者の方はallocの後で呼び出す初期化メソッドである
NSString
+ (id) stringWithCString:encoding:(const char*)cString
encoding:(NSStringEncoding)encding
- (id) initWithCString:encoding:(const char*)cString
encoding:(NSStringEncoding)encding
C言語の文字列cStringとそのテキストエンコーディングencodingを指定して,
インスタンスを作ります
文字列の作成
これらのメソッドは1つめの引数にC言語の文字列を指定する
2つめの引数でエンコーディングを指定する
C言語の文字列はソースコードファイルのテキストエンコーディングが
そのまま使われる
ファイルのテキストエンコードを日本語のものにして,それを2つ目
の引数に指定してやればよい
+ (id) stringWithCString:encoding:(const char*)cString
encoding:(NSStringEncoding)encding
文字列の作成
例の紹介
まずソースコードファイルのテキストエンコーディングを設定する
Xcodeの[表示]→[テキスト]→[ファイルエンコーディング]メ
ニューを使う
[日本語(Shift JIS)]にして,以下のようなコードで文字列を作る
ポイントは引数の文字列には@をつけない事,
エンコーディングの引数をファイルのエンコーディングと
同じにする事
フォーマットからの作成
フォーマットを指定して文字列作成もできる
フォーマットはprintf文で指定するものと同じ置換子を使うもの
stringWithFormat:というメソッドを使う
printfのときと同様に可変引数を使う
フォーマット自体もNSStringで指定する事に注意
NSString
+ (id) stringWithFormat:(NSString*)format...
- (id) initWithFormat:(NSString*)format...
フォーマットでformatを指定して,インスタンスを作ります.
フォーマットからの作成
このメソッドで使える置換子はprintfのものとほぼ同じ
ただNSStringのインスタンスも「%@」という置換子で指定できる
置換子 説明
%@ NSStringのインスタンス
%d,%D,%i 整数
%u,%U 符号なしの整数
%x 符号なしの整数を,小文字の16進数で表現
%X 符号なしの整数を,大文字の16進数で表現
%f 小数
%c 文字
%s C言語の文字列
%% %記号そのものを表現
フォーマットからの作成
stringBは
 Mac Book Pro
となる
stringCは
80%
となる
stringDは
0x50
となる
NSRange
構造体NSRangeはある範囲を表す
10文字の配列の「5文字目から3文字分」という具合で範囲指定したいと
きに使う
NSString
NSMakeRange(unsigned int location, unsigned int length);
範囲開始位置locationと,長さlengthを指定してNSRangeを作ります
実行結果は
location is 0, length is 5
となる
文字列の操作
文字列の長さを調べるにはlengthメソッドを使う
NSObject
- (unsigned int)length
文字列の長さを,文字数で取得します
実行結果は
length is 8
となる
文字列の操作
2つの文字列の連結
ある文字列の後ろに,別の文字列をくっつけて新しい文字列を作るもの
stringByAppendingString:,stringByAppendingFormat:
というメソッドを使う
NSObject
- (NSString*)stringByAppendingString:(NSString*)string
自分自身に,文字列stringを連結した新しい文字列を作成して,返します
- (NSString*)stringByAppendingFormat:(NSString*)format, ...
自分自身に,formatで指定された文字列を連結した新しい文字列を作成して,返します
文字列の操作
2つの文字列の連結
実行結果は
Mac OS X leopard
となる
実行結果は
leopard10.5
となる
文字列の操作
NSMutableStringの作成
可変文字でありNSMutableStringを使えば一度使ったインスタンス文字
を変更できる
stringのメソッドでは空の文字列を作る
NSObject
+ (id)string
空文字のインスタンスを作ります
+ (id)stringWithString:(NSString*)string
- (id)initWithString:(NSString*)string
文字列stringと同じ内容のインスタンスを作ります.
文字列の操作
NSMutableStringの作成
stringWithString:を使えばNSStringからNSMutableStingを
作る事ができる
文字列の操作
文字列の追加
NSmutableString
- (void)appendString:(NSString*)string
文字列stringを追加します
- (void)appendFormat:(NSString*)format, ...
formatで指定された文字列を追加します
実行結果は
Mac OS X
となる
文字列の操作
文字列の挿入��
NSmutableString
- (void)insertString:(NSString*)string atIndex:(unsigned)index
文字列stringを,インデックスindexに挿入します.
実行結果は
Mac Book Pro
となる
文字列の操作
文字列の削除
NSmutableString
- (void)deleteCharactersInRange:(NSRange)range
範囲rangeで指定した文字列を削除する.
実行結果は
ac
となる
おわり

More Related Content

More from hasegawa

Cocoa Pro09
Cocoa Pro09Cocoa Pro09
Cocoa Pro09hasegawa
 
Cocoa Pro08
Cocoa Pro08Cocoa Pro08
Cocoa Pro08hasegawa
 
Cocoa Pro07
Cocoa Pro07Cocoa Pro07
Cocoa Pro07hasegawa
 
Cocoa Pro5
Cocoa Pro5Cocoa Pro5
Cocoa Pro5hasegawa
 
Cocoa Pro4
Cocoa Pro4Cocoa Pro4
Cocoa Pro4hasegawa
 
Cocoa Pro01
Cocoa Pro01Cocoa Pro01
Cocoa Pro01hasegawa
 
Cocoa Pro03
Cocoa Pro03Cocoa Pro03
Cocoa Pro03hasegawa
 
CocoaPro02
CocoaPro02CocoaPro02
CocoaPro02hasegawa
 

More from hasegawa (8)

Cocoa Pro09
Cocoa Pro09Cocoa Pro09
Cocoa Pro09
 
Cocoa Pro08
Cocoa Pro08Cocoa Pro08
Cocoa Pro08
 
Cocoa Pro07
Cocoa Pro07Cocoa Pro07
Cocoa Pro07
 
Cocoa Pro5
Cocoa Pro5Cocoa Pro5
Cocoa Pro5
 
Cocoa Pro4
Cocoa Pro4Cocoa Pro4
Cocoa Pro4
 
Cocoa Pro01
Cocoa Pro01Cocoa Pro01
Cocoa Pro01
 
Cocoa Pro03
Cocoa Pro03Cocoa Pro03
Cocoa Pro03
 
CocoaPro02
CocoaPro02CocoaPro02
CocoaPro02
 

Cocoa Pro6