2010年8月30日月曜日

サンプルプログラムでNSRangeExceptionが発生

以下のソースコードが書籍に書かれており、その通りに実装してアプリケーションを実行させたところ、「NSRangeException」が発生してしまいました。

if (cell == nil) {
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell"
        owner:self options:nil];
    cell = [nib objectAtIndex:1]  ・・・a
}

デバッグをしたところ、(a)地点で例外がスローされていることが分かりました。そこでその部分について以下のような説明が書籍にありました。(著作権的に問題がありそうなので、文章はサマリーします。)

「再生利用可能なセルがなければ、nibからファイルを読み込む。objectAtIndexの呼び出しでは、Index:0の代わりにindex:1を使う。オブジェクト0はファイルのオーナーで、テーブルビューセルはindex:1に存在する。」

この文章を信じきった私は、objectAtIndexの引数が1であることが正しいと思い込んでしまい、このエラーを取り去るのに相当な時間を要しました。結果としては(a)のobjectAtIndexの引数を0にすることで正常に動作しました。なぜ、0で動作したかはこれから調べますが、書籍のサンプルコードが引数1で正しいとしている点も気になります。単なる間違いなら良いのですが。高いお金を出して書籍を購入している身としては、正しい情報を載せてほしいと願うばかりです。

2010年8月29日日曜日

iPhoneシミュレータで正常で、実機でエラーとなった(AudioToolbox.framework)について

アプリケーションで、ある条件時に効果音(wavファイル)を鳴らすプログラムを作成した際に、iPhoneシミュレータでは正常に動作するのに対し、iPhone実機に転送する為にビルドするとエラーとなる現象が発生しました。
これが直接的な原因かは不明であるが、AudioToolbox.frameworkをプロジェクトに追加する際に、フォルダーをコピーしてプロジェクトに追加してしまった為だと思われます。イメージファイル等はコピーでResourceフォルダに入れたので、それと同じ様にやってしまいました。
対処としては、コピーで追加したAudioToolbox.frameworkをまず削除し、再びプロジェクトに追加しました。追加する際にはコピーしないように「デスティネーショングループのフォルダに項目をコピーする」のチェックを外した状態で追加します。
その後、Device用にビルドを実行し、無事に実行することができました。

iPhone実行時のエラー:unrecognized selector sent to instance xxxxxxxxx

TabBarでビューを切り替えてPickerViewを表示するプログラムを作成し、シミュレータでアプリケーションを実行したところ、「unrecognized selector sent to instance xxxxxxxxx」というエラーが発生してプログラムが落ちてしまいました。
ネットで調べたところ、呼び出そうとしたメソッドがなかった場合に発生するエラーのようだ。デバッガコンソールにそれっぽいメソッドが出力されていたので、キーワード毎にソースコード内を検索してスペルミスを発見して対処した。コンパイラからはワーニングが出ていたのだが、ワーニングレベルではコンパイルが成功してしまうので、なかなかエラーが発見しにくい事例でした。

#PRAGMAの意味と使い方について

#pragmaで始まるソースコード行は、コンパイラへの指令なので、具体的なことはコンパイラに依存します。他のコンパイラもしくは、他の環境でとくに機能する必要のない指令です。pragmaticには、「おせっかい」と言う意味もあるらしいです。
#pragma指令は、IDEに対して指令を出して、エディターウィンドウの一番上のポップアップメニューのメソッドと関数に改行を入れるようにXcodeのエディタに指示しています。

  • 「#pragma mark -」は、ポップアップメニューに水平線を入れます。
  • 「#pragma mark Test Methods」とした場合は、ボールドで"Test Methods"という文言を作成します。
クラス内にたくさんのメソッドや関数を、#pragma指定を使って論理的にソースコードを整理することができます。これを活用することで、より目的のソースコードにたどり着けるようになります。

NSIntegerについて

NSIntegerの変数を定義する際、ポインタ(アスタリスク)が付きません。iPhoneでは、接頭辞の"NS"は通常、Foundation FrameworkからのObjective-Cクラスを示しますが、これについては、一般的な規則の例外であります。NSIntegerは常に、一つのintまたはlongの整数データ型として定義されます。NSIntegerを使用するのは、今コンパイルしているプラットフォームに最適なサイズをコンパイラが自動的に選んでくれます。32bitプロセッサと64bitプロセッサそれぞれのintを作成します。現時点では、64bitのiPhoneはないですが、将来はもしかすると出ているかもしれません。