2012年11月13日火曜日

iOS6非互換:画面回転について

iOS6になって画面回転挙動の違いやコーディング方法等、結構違いがあるようでコード修正が必要になります。 いまさらコアな部分は変更して欲しくないってのが正直なところですがアップルは良いと思ったら「スパッ」と変更してきますので追従するのが結構大変です。

いろんな方々がブログ等で相違点・対応策を公開されており、それらを参考に調べておりましたが少しはまってしまった点がありましたので記載したいと思います。

<相違点>
・画面向きの変更通知用に下記メソッドですがiOS5まではビューコントローラ生成時向きの変更が無くても呼び出されていましたが、iOS6では呼び出されないようになったようです。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration


メソッドの意味合いからすると画面向きが変更になっていないので呼び出されないのが正解かも知れませんが以前まではビューコントローラ生成時に呼び出されていたのでこのメソッド内で画面の方向を取得していました。

iOS6では呼び出されないので別の方法で現在のデバイス向きを取得する必要がありますが、以下のメソッドでは上手く取得できないケースがあります。

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

で、代わりの方法として以下のメソッドで現在のデバイス向きを取得できるようですのでこのメソッドにてデバイス方向の初期値を設定するよう修正したところ正常な動作を実現できました。

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];


メソッドの呼び出しタイミングとか呼び出し条件の変更等の非互換はテストでも見つけにくいバグ発生の原因になりますから勘弁して欲しいってのが正直なところですね。

<追加したコード>
- (void)viewDidLoad {
// 親クラスメソッド呼び出し
    [super viewDidLoad];
    
    // 現在のデバイス方向の取得
    UIInterfaceOrientation orientation = 
            [[UIApplication sharedApplicationstatusBarOrientation];
    [self willRotateToInterfaceOrientation:orientation duration:0];
}

2012年11月12日月曜日

iOS6非互換:NSTimerの挙動!?(原因判明)

アップルの技術者の皆様、XcodeやiOS6を疑って申し訳ございませんでした。(^^ゞ

原因が分かりました。 私のコーディング上の問題でした。

iOS6から生成したビューに対して「removeFromSuperview」が何故か呼び出されるようになっているため、このメソッドをオーバーライドしてNSTimerの停止処理(停止後、開放される)を組み込んでいたのでビュー生成後の初期処理内でNSTimerを生成して起動した直ぐ後に「removeFromSuperview」が呼び出されたため、NSTimerを停止しておりました。

メンバー変数「mTimerTask」に代入した場合のみタイマー停止処理が行われますが、代入しない場合はタイマー処理の参照が無いので停止されないので代入の有無で挙動が変わっていたようです。

対応としては「removeFromSuperview」のオーバーライドを止めて別のメソッドでタイマー処理を停止するよう修正したところ正常に動作するようになりました。

うーん、結構ハマってしまいました。

iOS6非互換:NSTimerの挙動!?

うーん、納得出来ない事象に見舞われています。(-_-;)

iOS5までは問題無く動作していたソースをXcode4.5.2でiOS6SDKでビルドすると上手く動作してくれない。

いろいろ調べたところ、どうも「NSTimer」でスケジュールした定期タスク(無限実行)が起動しておらず、これが原因で不具合が起きておりました。

って事でNSTimer部分を見てもおかしいところがない(そもそもiOS5シミュレータでは正常に動作する)がタイマー処理が起動していない。

<タイマー処理が起動されないソース>
    mTimerTask = [NSTimer scheduledTimerWithTimeInterval:0.5f
                                                  target:self
                                                selector:@selector(_performTimer:)
                                                userInfo:nil
                                                 repeats:YES];


<タイマー処理が起動するソース>
    [NSTimer scheduledTimerWithTimeInterval:0.5f
                                     target:self
                                   selector:@selector(_performTimer:)
                                   userInfo:nil
                                    repeats:YES];

見ての通り、NSTimer部分は全く同じでメンバー変数に代入しているかしていないかの違いのみにも関わらず前者は起動せず、後者は正常にタイマー処理が起動します。

ちなみに代入先の「mTimerTask」変数はプロパティ定義ではなく単純なNSTimer*の変数定義です。
  (変数定義) NSTimer  *mTimerTask;

代入部分の違いだけでタイマー処理が起動しなくなるって「どういうこと?」って感じで納得出来ない状況なので、もしかしたらXcodeコンパイラかiOS6に問題があるんじゃないかと思いたくなるような状況ですね。

2012年11月10日土曜日

iOS6非互換:デバイスと画面回転の不一致

iOS6のiPad(実デバイス)での拙作アプリ動作確認では特に問題無く動作していたんですが、iOS6シミュレータで実行すると画面の回転制御がおかしいのか横画面の筈がデバイスは縦状態になり、画面だけが横表示されるのでデバイスの向きと画面表示がずれる現象が発生していました。

iOS4.3やiOS5.1のシミュレータでは問題無く表示されるのでiOS6からの非互換のようです。

<原因>
・UIWindowクラスのrootViewControllerプロパティにViewControllerインスタンスを設定する必要があるようです。

<対応>
・rootViewControllerプロパティにビューコントローラーを設定するコードを追加。


// View表示切替
[window addSubview:theViewController.view];
[self.viewController.view removeFromSuperview];
self.viewController = theViewController;
// 2012/11/10 ADD_START: iOS6非互換対応
 self.window.rootViewController = theViewController;  …追加コード
// 2012/11/10 ADD_END
[window makeKeyAndVisible];


上記のようにrootViewControllerプロパティに代入するとデバイスの向きと画面の向きが合いました。

ではまた~

半年ぶりの投稿。。。(^^ゞ

久しぶりの投稿です。 半年以上。。。(^^ゞ

やっと本業の案件が一段落しましたんでiOS開発に復帰です。

Macを起動することも時間が開いてたんでまずは「システムアップデート」を実施。
XcodeもiOS6対応版がリリースされてたんで「Xcodeアップデート」も実施しました。

久しぶりにXcodeを起動しましたが見た目は大きく変わってませんが操作方法(キーボードショートカット)とか思い出せない。。。(-_-;)

ソース自体もObjective-C独特の"["や"]"が連なるコードに違和感を感じますね〜。

と、感慨に耽っている時間もそこそこに手探りながらXcodeの開発に戻りたいと思います。