2015年9月28日月曜日

iOS9の変化点

iOS9で変わった点を記録していく。

(1)フォントサイズが変わった
X-BASIC'では同じフォントを使っていても表示サイズが異なる結果になる。iOS9のほうが一回り小さい。
アップルのフォントは小さすぎて、高齢者に優しくない。

(2)バックグラウンドでreallocできなくなった
実行時に
「This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes.  This will cause an exception in a future release.」
が発生する。一応警告(とダンプ)だけで今は動いているようだが、将来的には落ちると書いてあるので対策したほうが良さそう。一番単純な対策はその部分をメインスレッドで行うようにすればいいのだが、reallocだけメインに持っていくのは無理。全体の動作の見直しが必要。

realloc以外でも発生する可能性はある。


(3)Autoresizeの結果がviewWillAppear時点で得られなくなった。
 こんなん仕様変更とは言わない。大バグ。
 仕様変更なら変更で仕様書に書け。書かれても許さないけど。

2015年9月19日土曜日

NSDataの内容をC的に変更する方法

NSDataは基本的には一度初期化するとその内容を変更することはできない。変更する場合はNSMutableDataを使うと。少なくともメソッドを使った方法ではその通りなのだが、C的に変更するなら方法がある。

NSMutableData *mdata〜
char *p=(char  *)[mdata mutableBytes];  

NSData *data=〜
char *p=(char  *)[data bytes];

とすると、内容を示すポインターを得られる。
ここでpのアドレスからに改変を加えるとNS(Mutable)Dataの内容が変わる。Mutableでなくてもいける。

NS(Mutable)Dataの中ではデータは連続した領域に保存されているようである。

ここ1つ注意すべきは、この方法で内容を更新するときは、絶対に元のデータの範囲を超えないこと。メソッドによるアクセスとは違い安全機構は働かないので確実にシステムが落ちる。

そしてもう1つ。この方法で書き換えても効果が出ないこともある。

AVAudioPlayerは内部でのデータの保持にNSDataを使っている。それは

AVAudioPlayer *av=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
char *p=[av.data bytes];

でアクセスできるが、ここでpからの内容を書き換えても音は変化しない。おそらくは、元の音声データが.dataにあるが、実際に音声出力用データはinitWith時に別に複製が作られているのではないかと思う。

確保した音声データを直接書き換え音を変更しようと思った実験の結果。

2015年9月3日木曜日

iOSシミュレーターの仕様(Xcode6.4/7.0編)

Xcode6.4/7.0でのiOSシミュレーターの隠れた仕様を列記しておこうと思う。
主に自分の忘備録。

・AudioToolbox.frameworkのAudioServicesPlaySystemSound()はiOS7では音が出ない
iOS8では音が出る。またAVAudioPlayerはiOS7でも大丈夫。
音が出ないから散々調べたらこれだった。

・実機にしかないハードウェア機能は当然使えない
カメラ、モーションなど

・eMailはOK
・AirPrintもOK

・アプリの言語切替は、シミュレーター上の設定〜一般〜言語環境ではなくXcodeのEditScheme〜Application Languageで切り替える
ただしこれで切り替わるのはアプリケーションの言語だけなので、OSの設定の言語は元のまま。なので、SettingBundleでOSの設定に追加している時にその言語別表示を確認するには、OSの言語設定も別途変更する必要がある。

・AVAudioEngine/AVAudioPlayer系でエラーが発生すると、Macの他のアプリからも音が出なくなってしまう
例えばChromeでGyaoを見てて、シミュレーター上でそこでエラーが発生すると、しばらくすると(おそらく先行でバッファリングしていた分の再生が終わると)音が出なくなる。治すには、再度RUNすればいい。

・ProfileでAlloc/LeaksはiOS8でしか動かない
iOS7ではエラーが出てしまう。
AppleはiOS7外しにかかっているのがよくわかる。でも、それを開発者に強要するのはどういうものかと。

・キーボードの設定はHardware〜Keyboardにある

・[UIDevice currentDevice]model]が"iPad Simulator"または"iPhone Simulator"としか返してこない
シミュレートするデバイスを切り替えても一緒。
これを使うなら実機が必須ということ。機種別切り替えが必要なプログラムのデバッグにはシミュレーターが使えないってどういうこと?

・Intervalが非常に短い間隔のNSTimerを発行すると正しい時間にならない。
1/10=0.1 秒くらいなら大丈夫そうだけど、1/1000秒を設定しても(実測で)約0.1秒になっている。iPad2を選択しているとうまく動 くのにiPad RetinaやAirを選んでいるとだめなので、それらだけのバグ。ちなみに、実機ではちゃんと動く。
→その後調べた結果、AppleのNSTimerのドキュメントに「the effective resolution of the time interval for a timer is limited to on the order of 50-100 milliseconds.」とあった。要するに0.05s〜0.1sより大きな数値でないと動作は保証しないということで、それ以下なら動いて御の字と言える。これでは音楽ドライバが作れない!!
→実験の結果、repeat:NOなら1ms(0.001s)単位でもほぼ正確にかかってる。実機、シミュレーターとも。repeat:YESでも30ms位ならほぼ大丈夫だけど極稀にダメみたい。
 X-BASIC'では画面更新とキーリピートが引っかかる。・・・

それはそうと、Xcode6.4/7はブレークポイントがおかしいと思うのだけど。
設定した場所で止まらない。
一見設定した場所で止まっているようで、実はぜんぜん違う場所で止まっていることが多発している。7.1でも直ってない。
このバグのせいでブレーポイントを使ったデバッグがまともにできない状態。
細かくNSLog()を入れて、チェックするしかない。
アップルはもっとデバッグして。