Camera Overlay Viewを設定するとiOS 7.0以降でアプリが操作不能になる問題への対処方法
少し前の話。UIImagePickerControllerを使った写真撮影機能を実装していたとき、iOS 7未満では何の問題もない次のようなコードをiOS 7.0以降で実行すると、シャッターボタンをタップして写真撮影を行ったぐらいのタイミングで以降のアプリ操作不能になる現象が発生した。
- (void)launchCamera { if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { UIImagePickerController *pickerController = [[UIImagePickerController alloc] init]; pickerController.sourceType = UIImagePickerControllerSourceTypeCamera; pickerController.delegate = self; UIImage *image = [UIImage imageNamed:@"OverlayImage"]; UIImageView *imageView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; imageView.image = image; imageView.contentMode = UIViewContentModeScaleAspectFill; imageView.userInteractionEnabled = YES; pickerController.cameraOverlayView = imageView; [self presentViewController:pickerController animated:YES completion:NULL]; } }
処理を部分的にコメントアウトしながら挙動を確認して直接の原因と思われる箇所を限定していくと、
pickerController.cameraOverlayView = imageView;
という処理が入っている場合にのみ現象が発生することが明らかになった。そこで、iOS 7におけるCamera Overlay Viewについて情報収集してみたところ、AppleのDeveloper Forumsでこの問題が取りあげられている場所があるのを発見した。(https://devforums.apple.com/message/890325#890325 。閲覧には開発者登録が必要。)
Developer Forumsでの回答を参考にすると、Camera Overlay ViewがpointInside:withEvent:でNOを返すようにすることでこの問題を解決できるようだ。そこで、UIImageViewのサブクラスを作成し、pointInside:withEventを次のようにオーバーライドするようにした。
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { return NO; }
このカスタムImage Viewクラスを使ってCamera Overlay Viewを設定したところ、iOS 7.0以降でも写真撮影後に正常に処理を継続することができるようになった。
以下は蛇足というか教訓というか。
UIImageViewPickerControllerのように、クラス自体は古くから存在している場合、これまでのバージョンのOSでは正常動作しているコードでも、新しいバージョンのOSでのみ問題となることがある。そのようなときに、いざ原因特定のための情報収集してみると、クラス名等のキーワードだけでは無関係の情報がヒットしやすく、調査が少々難航してしまう。
新しいOSバージョンでのみ発生する問題について調査する場合、(少なくともiOSやOS Xに関する問題については)Developer Forumsは比較的に質の高い情報が得られるのだと実感した。iOS 7はiOS 6までと比べてリリース直後のこのようなちょっとした問題に遭遇することが多いので、意識的にDevelop Forumsを活用していこうと思った。