2010年11月25日木曜日

UIViewの追加・削除

UIViewにUIViewを追加するには、addSubviewメソッドを使用します。
addSubviewにはUIViewクラスか、UIViewを継承したクラスのインスタンスが指定できます。


[self.view addSubview:UIViewクラスを継承したクラスのインスタンス];

上記でself.viewに指定したUIViewが追加されます。

一度addしたUIViewを削除するには、removeFromSuperviewメソッドを使用します。

[UIViewクラスを継承したクラスのインスタンス removeFromSuperview];

上記で指定したインスタンスの解放まで行ってくれますので、releaseは不要です。


2010年11月11日木曜日

スレッド

IOS4からiPhoneでもスレッドが使えるようになりました。
スレッド呼び出しは、UIViewの「performSelectorInBackground」メソッドを使用します。

performSelectorInBackground:スレッドのセレクタ withObject:オブジェクト

例えば、ボタンがクリックされたら別スレッドで処理を走らせるには、以下のようにします。

-(IBAction) clickBtnStart:(UIButton*)sender
{
    // ラベルに別スレッドが走ることを表示
    label.text = @"Running background thread";

    // UIActivityIndicatorでwaitアニメーションさせる
    [activityIndicator startAnimating];


    // 別スレッドを呼び出し
    [self performSelectorInBackground:@selector(backgroundThread:) withObject:nil];
}

-(void) backgroundThread:(NSObject*)param
{
    NSAutoreleasePool* pool;
    pool = [[NSAutoreleasePool alloc] init];
   
    [NSThread sleepForTimeInterval:10.0];  // wait 10sec
   
    [activityIndicator stopAnimating];
    label.text = @"Finished";
    [pool release];
}

上の例は、ボタンがクリックされたらラベルに「Running background thread」と表示し、ActivityIndicatorでWaitのアニメーションをさせます。

backgroundThreadが別スレッドで動作する処理です。
「NSAutoreleasePool」というのは、インスタンス確保されたメモリを自動破棄する仕組みです。
NSAutoreleasePoolの生成からreleaseまでの間にインスタンスの確保が行われた場合、releaseでそれまで生成されたインスタンスを一括解放してくれるというものです。
ただ、自動で解放するという仕組みがなかなかくせ者で、思わぬクラスで自動解放されてしまったりすることがあるので注意が必要です。
上記の例ではインスタンス生成を行っていないので無意味ですが、忘れないようにとりあえず書いています。

NSThreadクラスの「sleepForTimeInterval」メソッドで10秒ウェイトさせた後、スレッドの処理が終了したことをラベルとActivityIndicatorのアニメーションをストップさせることで通知させています。

上記のようにすると、バックグランドスレッドで重い処理を行わせていても、メインスレッドにほとんど影響がないことが分かります。

2010年11月10日水曜日

サウンドの連続再生

ゲーム等でボタンを連射した時の様に、同じサウンドを連続して再生させるには、以下のようにします。




    // soundはAVAudioPlayerクラスのインスタンスです
    if( sound.playing ) {
        [sound pause];
    }
    sound.currentTime = 0;
    [sound play];



普通にstopしてplayすれば良さそうですが、実際にstop・playすると、再生が終了しないと次の再生が行われません。
ゆっくりした操作の場合はこれでも良いのですが、ゲームなどでボタンを連射する操作が必要な場合はサウンド再生が1テンポ遅れて聞こえてくるようになります。
上記のように、サウンドが再生中の場合はpauseメソッドで一時停止しておき、currentTimeプロパティで再生位置を最初に設定、その後、playメソッドで再生するというやりかたで、連射しても1テンポ遅れることなく再生されるようになります。

追記:
上記はAVAudioPlayerのplayingプロパティでサウンドが再生中だったらpauseメソッドで一時停止させていますが、この処理があると処理が若干重くなるようです。
ですので、以下のように判定処理自体を省いてしまってもいいかもしれません。


    sound.currentTime = 0;
    [sound play];

2010年11月5日金曜日

サウンドファイルの変換

IOSがサポートするサウンドには以下の物があります。

フォーマット内容ハードウェアサポート
CAFApple Core Audio(.caf)なし
ALACApple Lossless Audio Codec。可逆圧縮サウンド形式(.m4a)有り
AIFFAudio Interchange File Format(.aif, .aiff)なし
AACAdvanced Audio Coding:iTunes Storeの配信用(.m4a)有り
MP3MPEG Audio Layer-3音楽圧縮用(.mp3)有り

サポートファイルは他にもありますが、後述するafconvertコマンドで-hfオプションを付けると見ることができます。

ハードウェアサポート有りのものはCPU負荷が軽くなりますが、サウンドの同時再生は行えません。
逆にハードウェアサポートなしのものはCPU負荷が高くなりますが、サウンドの同時再生が可能です。

ファイル形式の変換はターミナルからafconvertコマンドを使用します。
以下は、sound.m4aファイルをsound.cafファイルに変換する例です。

/usr/bin/afconvert -f caff -d aac sound.m4a sound.caf

サポートファイルや形式名はafconvert -hfで見ることができます。

再生確認は、ターミナルからafplayコマンドを使用します。

afplay sound.caf


追記:
ちなみにMP3ファイルをcafファイルに変換するには、以下のようにします。

afconvert -f caff -d ima4 sound.mp3 sound.caf


WAV形式→caf形式は以下の様にします。

afconvert -f caff -d LEI16 sound.wav