Viewのローテーション通知処理を一時的に禁止する

何度か話題にしてきたカスタムなUIAlertViewだが、どうにもこうにも上手く制御できない。

  • あるデリゲートメソッドが意図せず呼ばれる
  • 同じデリゲートメソッドで振る舞いが変わる
  • オリエンテーション(向き)変更時のUIAlerViewのリサイズ/リレイアウトが上手くいかない

一番やっかいなのはデバイスのオリエンテーションに追従してUIAlertViewを回転させて、尚かつ位置とサイズを毎回同じにすることなのだが、それが上手くいかないのだ。

何度か対策を嵩じてきたがその度に上記の不具合が出てきて、今度はその穴を潰すためのアドホックなコードを書くということを繰り返してきたのだがもう限界だ。

これ以上この問題に時間を掛ける訳には行かない状況なので、大胆に以下のように仕様を変えることにした。

    • UIAlertViewを表示している最中だけVIewのオリエンテーションを禁止する

そもそもUIAlertViewを表示している時というのは処理の意思決定が必要な時であり、オリエンテーション変更は不要だと割り切ることにしたのである。(実際にそのように振る舞うアプリケーションがあるのも知っている)

そうと決まれば話は簡単だ。 ユーティリティに以下のようなデバイスのオリエンテーション通知を禁止/許可するクラスメソッドを用意する。

  • BBDeviceUtil.m
+  (void)prohibitChangeOrientation
{
    UIDevice* currentDevice = [UIDevice currentDevice];
    while ([currentDevice isGeneratingDeviceOrientationNotifications])
        [currentDevice endGeneratingDeviceOrientationNotifications];
}
+ (void)allowsChangeOrientation
{
    UIDevice* currentDevice = [UIDevice currentDevice];
    while (![currentDevice isGeneratingDeviceOrientationNotifications])
        [currentDevice beginGeneratingDeviceOrientationNotifications];
}

処理ではこのメソッドを適宜呼び出せば良い。

  • BBUIAlertView.m
- (id)initWith〜
{
    self.delegate = self;
} 
- (void)show
{
    //オリエンテーション変更通知の禁止
    [BBDeviceUtil prohibitChangeOrientation];
    [super show];
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    //オリエンテーション変更の許可
    [BBDeviceUtil allowsChangeOrientation];
}

こうしておけば少なくとも表示時にはオリエンテーション変更のことは考えなくても済む。

本当はこんなことをしなくても良いように完璧なUIAlertViewを書きたかったのだが、商用アプリケーションの開発では時間の優先度が高い場合があり、実装の妥協も必要になるのは仕方が無いことだ。

しかし、そのうちきちんと書き直すぞ。