投稿

AVQueuePlayer

AVQueuePlayer AVPlayerのサブクラス。 複数のアイテム(曲)を登録しておき一度の指令でそれらを連続再生出来る。 インスタンス生成時、または生成後の初期化時に、AVPlayerItemを含んだNSArrayを渡す。 再生途中に他のアイテムの追加が出来るのがすばらしい。再生が途切れることがない。 seekToTime:という指定した場所に再生場所を移動させるメソッドがある。これはAVPlayerから継承している。このメソッドでの指令の仕方の時間は1曲目の頭からの時間ではなく、その曲の頭からの時間。つまり5曲目再生中にseekToTime:で5秒を指定すると、5曲目の5秒のところに移る。 インスタンス作成 queuePlayerWithItems: 曲追加 insertItem:afterItem: プロパティ currentItem これはAVPlayerから継承。割り込みによる停止中でもnilにはならない。 全部の曲の再生が終わるとnilになる。 AVPlayerItem インスタンス生成時、または生成後の初期化時に、NSURLかAVAssetを渡す。 AVPlayer CMTime time = CMTimeMake(1800, 600); CMTimeGetSeconds(time)

Audio Session細かいことまとめ

SessionActive化のタイミング 電話がかかってきて電話に出た時は、End Interruptionが呼ばれないそうなので、どこでSessionをActiveにするか、検討する必要がある。 割り込みのタイミング アプリをバックグラウンドにしたときに音楽を再生していない場合は割り込みが入る(イニシャライズ時に指定した関数が走る)。再生している時は入らない。「何もしていないなら切りますよ」的なニュアンスで何かの処理が走る模様。割り込み関数が実際に走るのはフォアグラウンドにしたとき。begin分とend分の2回走る。 バックグラウンド機能のON OFFやmixWithOthersのON OFFも関係あります。 AVPlayerの割り込みメソッド呼び出しについて AudioSessionのイニシャライズ時に指定する割り込みメソッドは再生中で無くても呼ばれるが、AVPlayerの割り込みメソッドはplay中でないと呼ばれない。(検証不十分) AVPlayerの自動SessionActive機能について AVPlayerには割り込み完了時にSessionActiveをYESにする機能があるのだが、この機能が少し癖があるので気を付けたい。 まずはいろいろなパターンを調べた。割り込みはiOSに付属しているアラームを使った。ちなみにタイマーだと1つしか登録できないが、アラームだと複数登録できる。 パターン1:初めにアラーム設定し、アプリを起動する アラーム設定する アプリ起動 AVPlayerインスタンス作成 セッション初期化 セッションアクティブ化 アラーム発生 アラーム処理(OKをタップ) 次のアラーム発生で割り込みメソッドが呼ばれない → 自動でアクティブ化されない パターン2:アプリを起動してから一旦バックグラウンドにして、アラーム設定し、再びアプリを起動する アプリ起動 AVPlayerインスタンス作成 セッション初期化 セッションアクティブ化 アラーム設定する アプリ起動 AVPlayerインスタンス作成(viewDidLoadに入れていたので再び処理が走った) セッション初期化(viewDidLoadに入れていたので再び処理が走った) セッションアクティブ化(viewDidLoadに入れ...

Affine行列の適用順序

イメージ
しょっちゅう忘れてしまうので… 基本 CGではAffine行列は3x3の行列で a b 0 c d 0 tx ty 1 で表される。 この行列は元データである個々の座標に対して後ろから掛かり、適用後の座標を出す。 これは行列の中の移動を表すtx,tyの位置から明らか。 前から掛けると(行列)(縦表現座標)となり、結果は(ax+by,cx+dy,tx+ty+1)。これは求めたい結果ではない。 後ろから掛けると(横表現座標)(行列)となり、結果は(ax+cy+tx,bx+dy+ty,1)。こちらが求めたい結果。 ちなみに座標は(x,y,1)となる。最後の1は必要。 ということで 個々の座標データに行列を適用させるというのが行列の使われ方 座標に対して後ろから掛かる という前程で進める。 複数の行列の適用順序 CGAffineTransform t = CGAffineTransformIdentity; t = CGAffineTransformScale(t, 0.5, 2.0); t = CGAffineTransformTranslate(t, 100.0, 100.0); t = CGAffineTransformRotate(t, 1.0); とプログラムを書いた場合、最終的な行列tは (Rotate演算行列)(Translate演算行列)(Scale演算行列) の結果となる。 つまり、行列追加関数は既存の行列の前に新しい行列を挿入する。 これが座標に後ろから掛かるので、個々の座標データにRotate演算、Translate演算、Scale演算の順に実行されたことと同じ結果(実際には先に適用行列の積が計算されていて、その結果を座標データに適用すると思う)。この順番は関数が書かれている順番と反対。 上のはCGAffineTransformの場合だが、 drawRect内でCGContextRefに行列を与える関数 CGContextScaleCTM(context, 0.5, 2.0); CGContextTranslateCTM(context, 100,100); CGContextRotateCTM(context, 1.0); も同様の法則。 また、view.layerに与え...

C言語系のいろいろ

charを8ビットフルに正数として使う場合にunsignedは必要か char型をint型に何かの理由でキャストするときにcharの最上位ビットが1だとマイナスの値のintになってしまう。 charは文字なんだから正数(と0)しか扱わない前程で処理してくれるかと早とちりすると危険。 NSLogやprintfの引数として渡すときに、値を見ようとして%dを使った時も同様。ちなみに%uにするとめちゃくちゃデカイ値が表示されてかなりわけのわからん状態になる。 iOSアプリの開発だとcharを使う機会はかなり少ないので見落としやすい。 また、unicharというのもあって、そっちはもとからunsignedで宣言されていて紛らわしい。 ということで正数と0のみの場合はcharでもunsignedは必要。

Mac Fanの表紙が動きます(Mac Fan X ARART)

イメージ
Mac Fanの表紙が動きます。 Mac Fan (マックファン) 2013年 06月号の表紙がアマゾンで見れるようになりました。表紙の前田敦子さんの右肩あたりに 表紙が動き出す!! iPhoneアプリ「Mac Fan X ARART」で表紙を覗いてみよう という文字が見えます。どういうことでしょうか? このARARTとは iPhoneのカメラで取得した映像がディスプレイの中で動き出す というアート作品です。 例えば、花のつぼみの絵にカメラを向けてディスプレイに映すと、アプリの中でその映像を分析し、つぼみの位置のところを開花する花の動画に変換し表示します。ユーザーには現実の世界(つぼみ)とは違う別の世界(開花の様子)がディスプレイの中に見えます(まあこの拡張世界をどううまく作るかはセンスが必要ですが)。 下のが公式のビデオです。 ARARTチームはいろいろな会社の宣伝活動に技術を提供しているようです(たぶん)。 今回、このARARTがMac Fanの表紙で体験できるようになります。 Mac Fanの表紙用に作ったアプリ「Mac Fan X ARART」をダウンロードして紙面に向けて実行すれば出来ます。 Mac Fanがどのような世界を用意しているかは見てのお楽しみということで、とりあえずこのARARTというのをやってみます。 アプリはこちらで取得出来ます。(Mac Fan + ARARTのアプリとは別) ARART やり方は アプリをダウンロードとインストール 絵画が置いてあるサイトを表示 アプリを実行 です。 詳しく説明していきます。 アプリをダウンロードとインストール アプリを起動後に追加でインストールするデータがかなりあります。そちらは回線に余裕のある環境でダウンロードしてください。 サイトを表示 パソコンでこちらのサイトを表示します。 http://arart.info/museum/ 絵を紙に印刷してもアプリを実行できます。 アプリを実行 アプリを起動するとカメラ機能が有効になり、画面にはカメラに取り込んだ映像が表示されます。 まずは絵画が画面に入るようにして下さい。停止させた状態で少し(1〜2秒)経つと動画が始まります。 無理な体勢で全部の絵画を見ていくと手が疲れる...

Form Sheetの画面回転処理

あるViewControllerから別のViewControllerをモーダルで呼び出すときにform sheetという表示方法がある。このform sheetというのは画面全体を覆うのではなく"回"のように中央に小さなViewを表示するタイプ。 この呼びだされたもの自体もViewControllerなので、デバイス回転に対するメソッドを持つことが出来るが、form sheetの場合はその回転メソッドは無視して、呼び出し(親)の向きに従うようである。 iOS View Controllerプログラミングガイドにこう書かれています。 画面全体を占めないView Controllerは一般に、向きを考慮しなくても構いません。親View Controllerか ら描画領域を指定されるので、その中に描画すればよいのです。一方、ルートView Controller(ある いは画面全体を表すView Controller)は、デバイスの向きを意識することが多いでしょう。 ということで「親View Controllerか ら描画領域を指定される」に「向き」も含まれていると解釈すれば、親ViewControllerに従うという理解で良さそうです。 ただ、 iOS5とiOS6で挙動が若干違うようです。 記述してある対応画面が親コントローラと子コントローラで同じならばいいんですが、問題となるのはiOS5で違う場合の処理です。いろいろやってみたのですが、どうも法則がつかめず。 パターン1 親の対応方向が子の対応方向を含む わからない (例) 親コントローラ:全方向 子コントローラ:rightのみ iOS5 親は回転に反応せず。子はrightのみ。 iOS6 親が全方向に対応し、それに子も従う (例) 親コントローラ:全方向 子コントローラ:UpSideDownのみ iOS5 親は回転に反応せず。子はUpSideDownのみ。 iOS6 親が全方向に対応し、それに子も従う (例) 親コントローラ:全方向 子コントローラ:rightとUpSideDownのみ iOS5 親も子もrightとUpSideDown。 iOS6 親が全方向に対応し、それに子も従う (例) 親コントローラ:全方向 子コントローラ:portraitとUpSideDownのみ iOS5 親も子もpor...

NSStringいろいろ

NSStringについてのいろいろ。 記事を書いた時のiOSバージョンはiOS6.1.3です。 初期化時の複数バイトエンコーディングの扱い - (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding; は引数にencodingがあるが、複数バイトエンコーディングのものを指定すると、全て0となっているバイトで文字列末端とみなされるようだ。 例えば2バイトで 00000000 10101010 と表される文字があるとすると00000000のバイトを文字列末端とみなすらしい。 長い文字列のはずが、いきなり初めのほうで文字列が終わってしまう。 + (id)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc も同様。 上位8ビットが0の時だけでなく下位8ビットが0の時でも末端と見るようだ。 おそらく 8ビット毎に取り出して char selectedChar = 取り出し関数(); if(selectedChar == 0){ 末端処理 }else{ switch(エンコード){ 各エンコード別の処理 } } のような処理だ。 そもそも8ビットの0を内部に含むエンコーディングはC言語文字列の定義から外れるという考え方なんだろう。 対策は – initWithBytes:length:encoding:(これはどのエンコードでもいけそう) - initWithCharacters:length:(UTF-16限定?) + stringWithCharacters:length:(UTF-16限定?) などを使う。 第3水準、第4水準の漢字に対応しているか まず、漢字の分類方法なのだが、第1、第2、第3、第4とあり、数字が大きいほうに使用頻度の低い漢字が割り当てられている。 第4水準の初めの文字は「毎」のカンムリだけを取り出したようなもの。読み方はわからず。このブログでは表示出来ない。 で、この漢字をiOSで扱えるのか? Unicodeに含まれていれば対応しているんではないか?と思うかもしれ...