iOS8之后,UIActionSheet 更改父类于 UIAlertController 带来的兼容性问题。


最近在做项目中遇到一个UIAlertController弹窗的问题,困扰了我很久。今天终于解决了,特此记录一下,以便日后查阅。
第一次的代码如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#pragma mark - <----------- 打开相册或者相机 -------------->
- (void)openCameraOrPhotoLibrary{
//    创建对话框控制器对象
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"请选择相机或相册" preferredStyle:UIAlertControllerStyleActionSheet];
//    创建事件按键
    UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style: UIAlertActionStyleCancel handler:nil];
    UIAlertAction *camera = [UIAlertAction actionWithTitle:@"相机" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//        选择相机的方法
        [self chooseHeadImage:UIImagePickerControllerSourceTypeCamera];
    }];
    UIAlertAction *photoLibrary = [UIAlertAction actionWithTitle:@"相册" style: UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//        选择相册的方法
        [self chooseHeadImage:UIImagePickerControllerSourceTypePhotoLibrary];
    }];
//    添加事件按键到控制器对象
    [alertController addAction:cancel];
    [alertController addAction:camera];
    [alertController addAction:photoLibrary];
//    弹窗对话框视图
    [self presentViewController:alertController animated:YES completion:nil];
}
iPhone 模拟器上测试没有任何问题,但是当我换成 iPad 模拟器时,在运行完这个方法后,直接崩溃了,而且没有任何崩溃信息提示。在 iPad 真机上测试也是直接崩溃闪退。
刚开始以为是还以为是访问相册出错了,各种查资料,看到网上有说是什么横竖屏的问题,难道是我把横屏模式关了导致的?于是把控制横竖屏的 Landscape LeftLandscape Right都打开,还是一样的崩溃。
最后通过Breakpoint调试发现,运行到最后一步需要弹窗时崩溃的。[self presentViewController:alertController animated:YES completion:nil];这就尴尬了。难道是这个方法用错了吗?不能呀。
最后又想到 UIAlertController对之前的 iOS 版本兼容性有问题吗?于是把 Deployment Target 从8.0 一路上升到 9.2 还是同样一到需要弹窗这一步就崩溃。
最后的最后没办法了,那就换成之前的 UIActionSheet 这总可以了吧。于是代码又变成了下面这样:
1
2
	UIActionSheet *sheet = [[UIActionSheet alloc]initWithTitle:@"请选择" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"相机" otherButtonTitles:@"相册", nil];
    [sheet showInView:self.view];
到这一步可以弹窗了,难道真是这么个问题??
于是遵循两个协议,实现代理方法 先是按常规用了这个方法
1
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex;

结果这次倒是没有崩溃,却是抛出了一个异常

1
Warning: Attempt to present <UIImagePickerController: 0x7fc19c8c7e00>  on <RLConfigHeadImageViewController: 0x7fc19e174120> which is already presenting (null)

我去,这是什么鬼东西,网上查了查,还是兼容性问题。

在iOS8以前的方法里,直接在Click的委托事件里处理点击按键的事件就可以了
1
-(void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex;
但是 iOS8之后就不行了,抛出这个警告,并且取消弹出ImagePicker行为。原因在警告里说得比较明白了,因为已经有actionsheet存在了,不能present新的。此时我们选择新的委托方法didDismissWithButtonIndex,把之前需要的 click 方法里写的写在这个方法里就好了。这次就没有什么其他问题了。
1
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex;
在 iPhone 模拟器和 iPad 模拟器都没问题了。