2009年8月31日月曜日

iPhone:インスタンスの生成と破棄(その3)

引き続き、インスタンスの生成と破棄に関してまとめます。
(その1)(その2)も参照してください。

今回は、他のオブジェクトが生成したインスタンスをメソッドを通して受け取る場合を考えます。
受け取ったインスタンスがオーナー側で破棄された場合にも参照を継続できるようにする必要があります。そのための方法として以下の2つの方法があります。

(A)インスタンスを保持する場合
オーナー側と同じインスタンスを共有したい場合にこの方法を使用します。
勝手に破棄されないように、受け取った時点でretainを実行します。また、不要となった時点で必ずreleaseを実行します。

(B)インスタンスをコピーする場合
オーナー側とインスタンスを共有したくない場合に使用します。
(A)と比較するト余分にメモリを消費することに留意が必要です。

iPhone:インスタンスの生成と破棄(その2)

iPhoneにはガベージコレクションのような機能は無く、アプリケーション開発者は自らメモリ解放の管理をする必要があります。これは、安定したアプリケーションを作るためには特に重要なテーマだと思いますので、再度自分の理解をまとめ直します。

参照カウンタの考え方と自動破棄については前回記事を参照してください。

今回は、インスタンスを生成するオブジェクト(オーナー)がするべき処理を5つパターンに分けて整理します。

インスタンスを生成する目的
(A)生成したインスタンスをイベント処理中だけ、一時的に使用したいケース
>イベント終了時には、生成したインスタンスが確実に破棄される必要があります
(B)生成したインスタンスを、インスタンス変数に格納して保持したいケース
>イベント終了後もインスタンスが破棄されないで存続する必要があります

生成するインスタンスが自動破棄の対象か否か
(1)自動破棄の対象である(alloc/new/copy以外の方法で生成する場合)
(2)自動破棄の対象ではない(alloc/new/copyで生成する場合)

上記の組み合わせの4通りに加えて、(A-1)の例外的なパターンとして以下を挙げます。
(A-1')一時的に使用するインスタンスをイベント中に大量に生成するケース

以下、それぞれのケースについてシーケンスを図示します。


(A-1)一時使用目的のインスタンス/自動破棄対象
このケースでは特に気をつける点は有りません。生成したインスタンスはイベント終了時に自動的に破棄されます。
(A-2)一時使用目的のインスタンス/自動破棄対象外
このケースでは、自動破棄はされませんので、使用後、オーナーオブジェクトから忘れずにreleaseを実行する必要があります
(B-1)保持目的のインスタンス/自動破棄対象
保持目的のため、自動破棄されると困ります。何もしないとイベント終了時に破棄されてしまいますので、生成時にretainをしておく必要があります
(ここ少し自信が有りません。確認予定)

(B-2)保持目的のインスタンス/自動破棄対象外
このケースでは特に気をつける点はありません。

(A-1')一時使用目的のインスタンスを大量に生成する場合
(A-1)の例外的なケースです。生成するインスタンスが大量で、イベント終了まで待っているとメモリが不足してしまうような場合にこのパターンを検討する必要があります。

オーナーオブジェクトは自前のNSAutoReleasePoolを作成します。その後インスタンスを生成すると自前のNSAutoReleasePoolの方に登録されます。オーナーは任意のタイミングでNSAutoReleasePoolします。するとそれに登録されていたすべてのインスタンスが破棄されます。

単に破棄したいインスタンスにreleaseを送ってはいけないのかと思いましたが、それだと最終的にNSAutoReleasePoolが2重開放してクラッシュするとのことです。

MacBook Proのためのバッグを購入しました:Brenthaven Edge I for 13インチ MacBook


MacBook Pro 13.3インチを入れるためのバッグを購入しました。
Brenthaven Edge I for 13インチ MacBookをApple Storeで購入しました。
とてもコンパクトで軽く、頑丈です。

専用にデザインされているだけあってぴったりです。構造は、外側にプラスチックの板があってその内側に2cmくらいの衝撃吸収材です。Mac Bookはとても厳重に守られ、中で動くこともありませんのでとても安心感があります。
MacBook 13インチと比較するとProの方が少し薄いので厚さ方向には少し余裕があるようです。薄い雑誌くらいなら一緒に入ります。
他の収納ですが、表には小さめのポケットがあります。ACアダプタをいれるのにちょうどいいサイズです。裏側には書類等を入れるための薄いポケットがあります。
ジャストサイズ感がとても気持ちがいいです。ただし他の収納はほとんどありませんので、このバッグに他の持ち物も入れてこのバッグだけで出かける使い方はできません。大きめのバッグに入れてインナーとして使うか、もう一つバッグが必要です。

2009年8月30日日曜日

iPhone:インスタンスの生成と破棄(その1)

[1]インスタンスの破棄は参照カウンタに基づいて行われます。
  • インスタンス生成時 カウンタ+1
  • retainメソッド実行 カウンタ+1
  • releaseメソッド実行 カウンタ-1
カウンタが0になるとインスタンスは破棄されます。

[2]インスタンスの自動破棄
イベントが発生してアプリケーションの処理が実行されるとき、そのイベント処理内で生成したインスタンスを、イベント処理後に自動的に破棄する(releaseメソッドが実行される)仕組みがあります。インスタンスの生成の方法によって自動破棄の対象になるものとならないものがあります。

(A)自動破棄されないインスタンス
以下のメソッドで生成されたインスタンスは自動的に破棄されません。
  • alloc / allocで始まるメソッド
  • new / newで始まるメソッド
  • copy / copyで始まるメソッド
インスタンスが不要になった時点で明示的にreleaseを実行する必要があります。
(もしくは、インスタンス生成後にautoreleaseを実行することで自動的に破棄されるようになります。)

(B)自動破棄されるインスタンス
(A)以外の方法で生成されたインスタンスはイベント終了後に自動的に破棄されます。明示的にreleaseを実行する必要はありません。

2点注意があります。
・インスタンス変数に格納して保持したい場合
イベント後に破棄されてしまわないように、retainを実行してからインスタンス変数に代入する必要があります。
・イベント中に大量にインスタンス生成する場合
メモリの使用量を抑えるために自動破棄のネストを使用します。
アプリケーション内で独自のNSAutoReleasePoolを作成し、自動破棄処理させます。


for ( int i = 0 ; i<=100 ; i++ ) {
// NSAutoReleasePoolを生成
NSAutoReleasePool* arp = [[NSAutoReleasePool alloc] init];
// インスタンスを生成する処理
・・・
// NSAutoReleasePoolを破棄 > arpに登録された全てのインスタンスにreleaseが送られる。
[arp release];
}

[3]インスタンスを他から受け取って使う場合
以下の3種類の方法を使い分けます。

(A)受け取った後retainし、不要になったらreleaseする
インスタンス変数に代入する場合 かつ、他と同じインスタンスを共有したい場合

(B)受け取った後、copyし、不要になったらreleaseする
インスタンス変数に代入する場合 かつ、他と同じインスタンスを共有する必要が無い場合
この場合自分がオーナーになります。

(C)何もしないでそのまま使う
ローカル変数として使う(メソッドの中だけで使う)場合

iPhone:タイマー

(1)ヘッダでNSTimerのインスタンスを定義します。

NSTimer* timerClock;

(2)タイマーを生成します。
アプリケーションの起動時に生成したい場合、アプリケーションデリゲートに実装します。

- (void)applicationDidFinishLaunching:(UIApplication *)application {

 // Override point for customization after application launch
[window makeKeyAndVisible];

// タイマーを生成する
timerClock = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:@selector( timerExpired: )
userInfo: nil
repeats: YES ];
}


 
(3)タイマーから起動される処理を実装します。この関数を、タイマー生成時にselectorとして登録します。タイマーから起動される関数は以下の型である必要があります。

- (void) timerExpired: (NSTimer* ) theTimer
{

    // タイマ満了時の処理を記述する
}

Snow Leopardを導入

昨日、Snow Leopardをインストールしました。特に問題なく、スムーズにできました。

iPhone開発環境は、以下の手順でアップデートしました。
(1)OSをインストール
(2)XCode3.2をインストール(Snow LeopardのDVDから)
(3)iPhone SDK(for Snow Leopard)をインストール

一つだけトラブルが発生しました。
アップデート後にXCodeとiPhoneを接続すると"開発をサポートできません"と
いうエラーが出ました。
iPhoneの電源を一度切断して再起動すると直りました。

2009年8月20日木曜日

文字列操作について

(1)文字列を扱うクラスには以下の2つがあります。
  • NSString ・・・インスタンス生成後は変更不可能
  • NSMutableString ・・・インスタンス生成後も変更可能 NSStringのサブクラス
(2)NSString型の文字列定数

@"文字列"


(3)文字列の文字数を取得する


NSUInteger len = [ @"xxxxxxxx" length ];


(4)文字列の生成・コピー

NSString* str = [ NSString stringWithString: @"xxxxxxx" ];
NSString* str = @"xxxxxxx";

NSMutableString* str = [ NSMutableString stringWithString: @"xxxxxxx" ];


(5)書式指定して文字列生成

int min = 33;
NSString* str = [ NSString stringWithFormat: @"%d min" :min ]; -> str = "33 years old"
NSString* str1 = [ NSString stringWithFormat: @"%4d" :min ]; -> str = "33"
NSString* str2 = [ NSString stringWithFormat: @"%04d" :min ]; -> str = "0033"


(6)オブジェクトを埋め込む
NSString* name = @"xxxx";
NSString* str = [NSString stringWithFormat: @"name = %d" , name ]; -> "name = xxxx"
オブジェクトのdescriptionメソッドが呼び出され、文字列に結合されます。

(7)文字列の連結

NSString* str1 = @"My name is ";
NSString* str2 = [ str1 stringByAppendingString : @"xxxx" ];
-> str2 = "My name is xxxx"

NSMutableString* str = @"My name is ";
[ str appendString : @"xxxx" ];
-> str = "My name is xxxx"


(8)文字列の切り出し

unichar chr = [ @"abced" characterAtIndex : 3];
-> chr = "e"

NSRange range = { 1 , 3 }
NSString* str = [ @"abcde" subStringWithRange : range ];
-> str = "bcd"


(9)文字列の比較

NSString* str1 = @"aaa";
NSString* str2 = @"bbb";
if ( [str1 isEqualToString : str2 ] == YES ) {
// 一致した場合の処理を記述
}


(10)文字列の部分比較

NSString* str = @"abcde";
BOOL prefix = [ str hasPrefix : @"abc" ]; -> YES 先頭の文字列評価
BOOL suffix = [ str hasSuffix : @"cde" ]; -> YES 末尾の文字列評価

iPhone:アプリケーションデリゲートについて

Window-Based Templateを用いてプロジェクトを作成した時点でアプリケーションデリゲートを実装するための枠組みはできています。 WebAppDeelegateはUIApplicationDelegateプロトコルを実装しており、UIApplicationのdelegateに登録済みです。

後はデリゲートのメソッドをオーバーライドするだけです。




デリゲートはアプリケーションの起動や終了などの時にアプリケーション固有の動作を追加する必要があるときに使用します。




- (void)applicationDidFinishLaunching:(UIApplication *)application {

// Override point for customization after application launch
[window makeKeyAndVisible];

// アプリケーション固有の動作をここに記述する
}

任意のオブジェクトのクラスをNibファイルに作成する方法

(1)Libraryウィンドウから、Object(NXObject)を書類ウィンドウにドラッグ&ドロップ
(2)Objectを選択し、InspectorウィンドウのIdentity に切り替える
(3)Class Identity > Class で作成したいクラスを選択する
以上でNibファイル内に任意のクラスのオブジェクトを追加することができます。

2009年8月19日水曜日

iPhone:Window-Based Templateとターゲットアクションについて

ターゲット・アクション処理を実装するのは、参考書などの手順に従ってやれば簡単に出来ましたが、いまいちその操作の意味が実感できないため自分なりの理解をまとめてみます。
(1)Window-Based Templateを用いてプロジェクトを作成した場合の初期状態は以下のようになっています。
UIApplidcationはアプリケーションの本体です。UIApplidcationはデリゲートとしてWebAppDelegate(Project名が"Web"のためこの名前になっています。)を保持しています。また、UIWindowを保持しています。
(2)Windowに、Interface Builderを用いてLabelやButtonを追加します。
(3)WebAppDelegateにOutletとActionを定義します。イベントが発生した場合にメッセージを受け取り処理(アクション)を行うオブジェクトのことをターゲットと呼びます。つまり、ここではWebAppDelegateがターゲットです。ターゲットにするのは必ずしもWebAppDelegateである必要はありません。たまたますでに存在していたクラスを使っただけで、別のクラスを新規作成してもかまいません。デリゲートとターゲットアクションをはっきり区別する意味で、本来は別のクラスにした方が理解しやすいのではないかとも思います。

(4)Interface Builderを使ってOutlet/ActionをUIオブジェクトと関連付けます。また、アクションメソッドに処理を記述します。WebAppDelegateでは、OutletとしてLabelのインスタンスを保持していますので、Labelに対してテキストの変更などのメッセージを送ることが出来ます。

2009年8月18日火曜日

iPhone実機でアプリが動きました

実機でのテストができるようになりました。ほぼ手順に従ってできましたが、1カ所戸惑った点がありました。
プロビジョニングをダウンロードし、デバイスへインストールした後、コードへ署名する必要がありますが、XCodeのターゲットの情報でコード署名IDを選択できませんでした。
結果、以下の手順で問題なくビルドできるようになりました。
(1)AppIDは開発するアプリ毎に異なるIDを取得します。
(2)プロビジョニングをダウンロードしたあと、そのファイルをダブルクリックします。
これでiPhoneへのプロビジョニングのインストールがされます。かつ、XCodeに
(3)ターゲットを選択して情報を開き、”プロパティ”タブの”識別子”を入力します。これには、App ID Suffix(Bundle Identifier)を入力します。Prefix(自動的に生成されたコード)は含みません。
(4)ターゲットの情報の”ビルド”タブのコード署名IDを入力します。
プルダウンから、さきほどダブルクリックしたプロビジョニングの情報を選択できるようになっています。

以上でiPhone実機でのテストができるようになりました。
今後、新しいアプリを開発する場合、毎回(1)からの手順を繰り返します。

試しにいい加減なアプリを作成し、実機で動作確認することができました。

2009年8月17日月曜日

iPhoneをXCodeに接続

次にiPhoneをXcodeに接続しました。
MacとiPhoneをUSBで接続し、XCodeを起動します。
XCodeのウィンドウ>オーガナイザでデバイスを確認します。
ここで、一つ問題がありました。
iPhoneのOSが3.0.1で、iPhone SDKがそれに対応していないためiPhoneを3.0.0にRestoreする必要があるというメッセージが表示されます。

これは、Dev CenterのドキュメントにRestoreしない方法が掲載されていました。
コンソールで1つコマンドを実行することで問題を回避できます。

iPhone Developer Program登録完了

iPhone Developer Programに無事登録完了しました。

自動では認証ができず、手動で認証をする必要があるとのことで、 サポートのメールの返信でApple Storeでの購入時の情報(請求先氏名と住所、注文番号)を送りました。
その後、Profileの情報を修正したから再度Activationを試みるようにとのメールを受けとり、実行したところ成功しました。これでiPhone Dev Centerに入れるようになりました。

結局、なにが正解だったのかは分かりません。入力する情報に不備があったとしてもサポートですぐ対応してもらえるので、迷うよりとりあえず購入してみるのがよいと思います。

iPhone Developer Program のActivationに失敗

受け取ったメールからActivationを実行しましたが失敗しました。 以下のようなメッセージが表示されました。

We are unable to activate your iPhone Developer Program membership because we are unable to successfully verify your identity. Please contact us and reference Enrollment ID# xxxxxxxxxx for further assistance.

contact usフォームから、どのように対処すればよいかを問い合わせました。おそらく、氏名や住所の文字化けが原因ではないかと思います。

2009年8月16日日曜日

iPhoneのiPod機能はプレイリストフォルダを使用できない

iPhoneに英語勉強用の音声を同期しようとしてiPhoneのiPod機能はプレイリストフォルダを使用できないことを知りました。
英語の勉強のためにかなり多数のプレイリストを使用しますのでフォルダがないと管理できません。残念ながらiPod nanoを継続して併用する必要があります。

(8/31更新)
やはりiPhoneの画面サイズと操作に慣れるとnanoに戻ることは出来ず、我慢してiPhoneを使うことにしました。全てのプレイリストを出すと多すぎるので、その日必要なプレイリストだけを入れるようにしています。

iPhone SDKを入手

iPhone SDKを入手し、こちらに従って一通りやってみました。iPhone シミュレータでのテストまでは特に問題なくできました。
実機でテストするために、iPhone Developer Programの登録が必要ですので手続きを始めました。
Profile入力時の文字化けの対処がわからず戸惑いました。当初Itunes StoreでApple IDを作成した際に入力した氏名や住所の日本語が全て”??”になってしまいます。
とりあえず日本語で再入力してApple Storeで購入をしました。24時間以内に今後の手続きのためのメールを受け取る予定です。

2009年8月8日土曜日

MacBookを購入しました

MacBook Proを購入しました。
初期設定だけ完了しました。

使えるようになるまでの時間がWindowsと比べて圧倒的に早いし、迷うようなところもありません。Macは本当に良くできてると思いました。

2009年8月5日水曜日

パケット代の節約

データ通信の送信と受信の和が1.5MB以内になるように気をつけます。
 設定>使用状況
料金プランの上限と下限をバイト数で計算すると以下のようになります。
 下限 1,029円 12,250パケット 1531.25KB
 下限 4,410円 52,500パケット 6562.5KB
 1パケット=0.125KB
 0.084円/パケット
とりあえず以下の対策で1.5MB以内に出来るか、来月試してみます。
・メールのプッシュ、自動的なフェッチはOFF
 無線LAN環境にあるときに手動で送受信します。
 設定>メール/連絡先/カレンダー>データの取得>プッシュ=OFF
 設定>メール/連絡先/カレンダー>データの取得>フェッチ>手動にチェック
・Safari、地図など明らかにデータ通信するアプリは 無線LANでのみ使用します。
・カメラの位置情報などで少しずついつの間にかデータ通信が増えていくようですがこれは黙認します。
これで目標を超えるようなら、位置情報のOFFや完全に3Gでのデータ通信を禁止する設定を検討します。

(8/31追記)半月程度で目標の1.5MBを超えました。
位置情報をOFFにして様子を見ていますが、それ以降は通信量が勝手に増えていません。
GPSが付いているのになぜ位置情報でデータ通信なのか理解できませんが・・
今後は位置情報OFF(写真等、使うときだけON)のつもりです。

モバイルポイント接続

モバイルポイントに接続してみました

昨日、前もって家のwifiでEメール(i)のアドレスとパスワードを変更し、モバイルポイントのプロファイルをインストールしておきました。

MySoftbankに接続するにもデータ通信料が掛かるそうなので、わざわざ家でやってきました。

幸いにもモバイルポイントは会社の近くにあります。
これを使うことで今のところ、データ通信料金は最低額に抑えるつもりでいますが自制できるかは分かりません。


忘れないように書きます。

iPhone(3G/3GS)でスクリーンショットをとる方法
 ホームボタンを押しながらスリープボタンを押すと
 カメラロールにスクリーンショットが保存されます

花火を見に行きました



花火を見に行きました。
写真はiPhoneではなくGR Degital IIです。

2009年8月4日火曜日

IPhoneを購入

8/2(日) iPhoneを買いました。(3GS 16G 黒)アプリ開発をやってみたくなったため。Macは追って購入予定。

同日、自宅に無線LANを導入するため、Air Mac Expressを購入しました。

無線を使えるPC/Macが無い状態でAir Macの設定が出来るか少し不安がありましたが、少してこずったあと、無事設定完了しました。

書籍「基礎からのiPhone SDK」も購入、MacとSDKを手に入れるまで予習を始めます。

8/3(月) iTunesのアカウントを作成しました。いくつかFreeのアプリを入手して遊びました。「基礎からのIPhone SDK」を読み始めました。