其他人在iOS 8中遇到UIImagePickerController
的问题吗?下面的方法在iPad上的iOS 7中运行得非常好,但是当我尝试呈现选择器(最后一行)时,我在XCode 6(Beta 3或4)中运行时会出现以下错误。如果重要,那么sourceType的选择来自于在同一个地方呈现的alertView。
Warning: Attempt to present <UIImagePickerController: 0x7c0ae400> on <CAGUCreateContactViewController: 0x7bf61a00> which is already presenting (null)
打开imagePicker的方法。
- (void)openPhotoPicker:(UIImagePickerControllerSourceType)sourceType
{
if ([UIImagePickerController isSourceTypeAvailable:sourceType]) {
NSArray *availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:sourceType];
if ([availableMediaTypes containsObject:(NSString *)kUTTypeImage]) {
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.modalPresentationStyle = UIModalPresentationFullScreen;
imagePickerController.sourceType = sourceType;
imagePickerController.mediaTypes = @[(NSString *)kUTTypeImage];
imagePickerController.delegate = self;
self.imagePickerController = imagePickerController;
if (sourceType == UIImagePickerControllerSourceTypeCamera) {
[self presentViewController:self.imagePickerController animated:YES completion:nil];
} else {
if (self.popoverVC) {
[self.popoverVC dismissPopoverAnimated:YES];
self.popoverVC = nil;
}
self.popoverVC = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
[self.popoverVC presentPopoverFromRect:self.nameAndPicCell.picture.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
}
}
}
答案 0 :(得分:108)
我认为这是因为在iOS 8中,警报视图和操作表实际上是视图控制器(UIAlertController
)。因此,如果您正在呈现新的视图控制器以响应UIAlertView
中的操作,则会在UIAlertController
被解雇时显示该视图。我通过将UIImagePickerController
的表示延迟到runloop的下一次迭代来解决这个问题,通过这样做:
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self openPhotoPicker:sourceType];
}];
但是,解决此问题的正确方法是在iOS 8上使用新的UIAlertController
API(即使用if ([UIAlertController class])
...来测试它)。如果您尚未使用新API,这只是一种解决方法。
答案 1 :(得分:80)
我同意Ben Lings的问题检测。在使用UIActionSheet时,我会建议一个更简单的解决方案。我只是简单地移动了我的代码,该代码对Action Sheet的选择做出了反应:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex;
{
// my code
}
成:
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex; // after animation
{
// my code
}
这样,应用程序可以保证在UIActionSheet动画完成后将执行代码。
由于UIAlertView具有类似的委托方法:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex; // after animation
{
// my code
}
我认为类似的解决方案可能适用。
答案 2 :(得分:12)
这是一个适合我的解决方案
if([[[UIDevice currentDevice] systemVersion] floatValue]>=8.0)
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self presentViewController:cameraUI animated:NO completion:nil];
}];
}
else{
[controller presentViewController:cameraUI animated:NO completion:nil];
}
请记得分配cameraUI
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
Build and Go!
答案 3 :(得分:8)
我在iOS 8中遇到了同样的问题。 然后我看到了iOS上最新更新的更改日志,即设备上的8.0.2。
本次更新中提到_
&#34;修复了导致某些应用无法访问照片库中的照片的问题&#34;
因此,在iOS 8.0.2版本的设备上使用XCode 6测试您的应用程序,它可以正常工作 不要在iOS 8.0模拟器上测试它。
这对我有所帮助,希望对你有同感。
答案 4 :(得分:4)
UIImagePickerController *imagePickerController= [[UIImagePickerController alloc] init];
[imagePickerController setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
// image picker needs a delegate so we can respond to its messages
[imagePickerController setDelegate:self];
self.shouldCallViewWillAppear = NO;
if(IS_IOS8)
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// Place image picker on the screen
[self presentViewController:imagePickerController animated:YES completion:nil];
}];
}
else
{
[self presentViewController:imagePickerController animated:YES completion:nil];
}
答案 5 :(得分:3)
您可以使用
关闭呈现的视图控制器(如果有)[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
这对我有用。
答案 6 :(得分:2)
您需要做的就是解雇已经呈现的ViewController:
if (self.presentedViewController) {
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
[self openPhotoPicker:sourceType];
如果仍然产生错误,请将openPhotoPicker:放入完成处理程序
答案 7 :(得分:1)
在iOS 8上,您应该使用新的API:
if (SYSTEM_VERSION_IOS_8) {
self.imagePickerController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popPC = self.imagePickerController.popoverPresentationController;
popPC.barButtonItem = self.popoverItem;
popPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:self.imagePickerController animated:YES completion:nil]
}
我建议您观看2014 WWDC session 228 a look in side presentation controllers
答案 8 :(得分:1)
我只是这样做了:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,
(unsigned long)NULL), ^(void) {
[self retractActivePopover];
dispatch_async(dispatch_get_main_queue(), ^ {
_activePopover=imagePickerPopover;
UIBarButtonItem *callingButton = (UIBarButtonItem*) sender;
[imagePickerPopover presentPopoverFromBarButtonItem:callingButton permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
});
});
答案 9 :(得分:1)
我经历了很多痛苦,提出了一个适用于iPad和iPhone的解决方案,这是最终的代码,其中一些来自其他人的评论: 代码有一些错误,但它是一个非常好的起点:)
定义:
__weak IBOutlet UIButton *attachButton;
UIImage *image;
按钮的操作:
- (IBAction)doAttach:(id)sender {
UIActionSheet *action = [[UIActionSheet alloc] initWithTitle:@"Select image from" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"From library",@"From camera", nil] ;
[action showInView:self.view];
}
#pragma mark - ActionSheet delegates
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if( buttonIndex == 1 ) {
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(authStatus == AVAuthorizationStatusAuthorized)
{
NSLog(@"%@", @"You have camera access");
}
else if(authStatus == AVAuthorizationStatusDenied)
{
NSLog(@"%@", @"Denied camera access");
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if(granted){
NSLog(@"Granted access to %@", AVMediaTypeVideo);
} else {
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@“no camera access“
message: @“if you need to use camera in this application go to settings -> appName -> and turn on camera.”
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@“ok” style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
NSLog(@"Not granted access to %@", AVMediaTypeVideo);
return ;
}
}];
}
else if(authStatus == AVAuthorizationStatusRestricted)
{
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@“no camera access“
message: @“if you need to use camera in this application go to settings -> appName -> and turn on camera.”
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@“ok” style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
NSLog(@"%@", @"Restricted, normally won't happen");
}
else if(authStatus == AVAuthorizationStatusNotDetermined)
{
NSLog(@"%@", @"Camera access not determined. Ask for permission.");
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if(granted){
NSLog(@"Granted access to %@", AVMediaTypeVideo);
} else {
NSLog(@"Not granted access to %@", AVMediaTypeVideo);
return ;
}
}];
}
else
{
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@“No camera access“
message: @“error accusing camera”
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@“ok” style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
return;
//NSLog(@"%@", @"Camera access unknown error.");
}
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIImagePickerController *pickerView =[[UIImagePickerController alloc]init];
pickerView.allowsEditing = YES;
pickerView.delegate = self;
pickerView.sourceType = UIImagePickerControllerSourceTypeCamera;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
[ self.presentedViewController dismissViewControllerAnimated:YES completion:nil ];
pickerView.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popPC = pickerView.popoverPresentationController;
popPC.sourceView = attachButton;
popPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:pickerView animated:YES completion:nil];
} else {
[self presentModalViewController:pickerView animated:YES ];
}
}
}else if( buttonIndex == 0 ) {
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
switch (status) {
case ALAuthorizationStatusRestricted:
case ALAuthorizationStatusDenied:
{
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@“no access to library”
message: @“if you wish to access photos in this app go to settings -> appName-> and turn on photos .”
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@“ok” style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}
break;
default:
{
UIImagePickerController *pickerView = [[UIImagePickerController alloc] init];
pickerView.allowsEditing = YES;
pickerView.delegate = self;
[pickerView setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
[ self.presentedViewController dismissViewControllerAnimated:YES completion:nil ];
pickerView.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popup = pickerView.popoverPresentationController;
popup.sourceView = attachButton;
popup.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:pickerView animated:YES completion:nil];
} else {
[self presentModalViewController:pickerView animated:YES ];
}
}
break;
}
}
}
#pragma mark - PickerDelegates
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
[self dismissModalViewControllerAnimated:true];
UIImage * img = [info valueForKey:UIImagePickerControllerEditedImage];
image = img;
}
答案 10 :(得分:0)
performSelector:withObject:afterDelay解决了我的问题。
还有didDismissWithButtonIndex可以做到这一点。
最高
答案 11 :(得分:0)
这是一个Xamarin解决方案。对我有用的是将我的动作添加到Dismissed事件处理程序。
this.btnPhoto.TouchUpInside += (sender, e) =>
{
actionSheet = new UIActionSheet ("Add Photo");
actionSheet.AddButton ("Take Photo");
actionSheet.AddButton ("Select from Library");
actionSheet.AddButton ("Cancel");
actionSheet.DestructiveButtonIndex = -1; // red
actionSheet.CancelButtonIndex = 3; // black
actionSheet.Clicked += delegate(object a, UIButtonEventArgs b)
{
actionSheet.Dismissed += (object aSender, UIButtonEventArgs dismissArgs) =>
{
switch (dismissArgs.ButtonIndex)
{
case 0:
showCamera ();
break;
case 1:
showPhotoLibrary ();
break;
}
};
};
actionSheet.ShowInView (view);
};