Cocoa Pro6

473 views
440 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
473
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Cocoa Pro6

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

×