UIPopoverController和UIActionSheet在iPad中使用

来源:互联网 发布:windows live64位下载 编辑:程序博客网 时间:2024/06/01 22:59

UIPopoverController和UIActionSheet在iPad中使用

这两天在做iPad版的应用,其中使用到了UIPopoverControllerUIActionSheet做相片获取,其中遇到了一些问题,总结如下:


UIActionSheet

当用户点击弹出UIActionSheet,选择相机或相册按钮时启动UIImagePickerController

代码如下:

- (void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{    if(buttonIndex==actionSheet.cancelButtonIndex) return;    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];    imagePicker.delegate = self;    if (buttonIndex == 0) {        //拍照        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {            imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;            imagePicker.allowsEditing = YES;            [self presentViewController:imagePicker animated:YES completion:nil];        }    }    else if (buttonIndex == 1) {        //相册        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {            imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;            [self presentViewController:imagePicker animated:YES completion:nil];        }    }}

当iOS7下执行相册,程序正常调取相册。当iOS8执行相册,则提示如下警告

2015-07-10 17:03:14.771 iPadTest[3353:95820] Warning: Attempt to present <UIImagePickerController: 0x7b3e3400> on <MasterViewController: 0x79a7cd00> which is already presenting (null)

相册无法正常启动。

同理在如下代码:

- (void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{    if(buttonIndex==actionSheet.cancelButtonIndex) return;    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];    imagePicker.delegate = self;    if (buttonIndex == 0) {        //拍照        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {            imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;            imagePicker.allowsEditing = YES;            [self presentViewController:imagePicker animated:YES completion:nil];        }    }    else if (buttonIndex == 1) {        //相册        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {            imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;            pc = [[UIPopoverController alloc]initWithContentViewController:imagePicker];            pc.popoverContentSize = CGSizeMake(100, 200);            [pc presentPopoverFromRect:CGRectMake(self.view.bounds.size.width-10, -10, 10, 10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];        }    }}

在iOS7下执行相册,程序正常调取相册。当iOS8执行相册,则提示如下警告

2015-07-10 17:18:30.296 iPadTest[3611:102813] Warning: Attempt to present <UIImagePickerController: 0x7cac0a00>  on <MasterViewController: 0x7be73f30> which is already presenting (null)

两种不同的相册打开方式,在iOS7和iOS8是相同的结果。

为什么呢?

如果把启动的方法替换如下:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{                [self presentViewController:imagePicker animated:YES completion:nil];}];

[[NSOperationQueue mainQueue] addOperationWithBlock:^{                    pc = [[UIPopoverController alloc]initWithContentViewController:imagePicker];                    pc.popoverContentSize = CGSizeMake(100, 200);                    [pc presentPopoverFromRect:CGRectMake(self.view.bounds.size.width-10, -10, 10, 10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];}];

相册可以正常打开,同理,相机和相册的打开、关闭在iOS8下都需要通过

[[NSOperationQueue mainQueue] addOperationWithBlock:^{    }]

dispatch_async(dispatch_get_main_queue(), ^{        });

这样就避免了无法启动或无法关闭的异常问题。

问题解决了,但原因是为什么呢?

经过测试、数据抓取

iOS7下UIActionSheet 调取- (void)showInView:(UIView *)view方法打印信息如下:

<UIActionSheet: 0x7a6524d0; frame = (0 0; 272 136.5); opaque = NO; layer = <CALayer: 0x7a940050>>

iOS8下UIActionSheet 调取- (void)showInView:(UIView *)view方法打印信息如下:

<UIActionSheet: 0x7a7859b0; frame = (0 0; 0 0); layer = <CALayer: 0x7a728bd0>>

官方文档介绍:

Important:  UIActionSheet is deprecated in iOS 8. (Note that UIActionSheetDelegate is also deprecated.) To create and manage action sheets in iOS 8 and later, instead use UIAlertController with a preferredStyle of UIAlertControllerStyleActionSheet.

意思是UIActionSheet在iOS8后废弃(过时),包括UIActionSheetDelegate。使用UIAlertController配合preferredStyle样式来实现想要的效果。

结论:
UIActionSheet在iOS7可用,iOS8下使用需要添加到主线程,才能响应,但建议使用UIAlertController实现自己的样式和功能。

该例子的demo

0 0