关闭 UIImagePickerController 也会使父级消失
Posted
技术标签:
【中文标题】关闭 UIImagePickerController 也会使父级消失【英文标题】:DIsmissing a UIImagePickerController is also making the parent dissapear 【发布时间】:2013-10-03 02:28:38 【问题描述】:我正在使用下面的代码来展示一个 UIImagePickerController 来拍照:
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setDelegate:self];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentViewController:imagePicker animated:YES completion:nil];
注意:self 是一个嵌入在 Container View 中的 UIViewController,它本身参与了 UINavigationController
而且我还实现了以下方法:
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
[self.imgProfile setImage:image];
[self dismissViewControllerAnimated:YES completion:nil];
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
[self dismissViewControllerAnimated:YES completion:nil];
当我选择拍摄的照片或取消它时,UIImagePickerController 消失了,但主视图也消失了!逐渐变黑。
我正在为仅 iPad 的应用程序编写 ios7 代码,以防它与它有关。
这是一个显示问题的视频。原谅模糊,但它在 NDA 之下。
http://www.youtube.com/watch?v=sIaPyRlIqyE
【问题讨论】:
尝试在picker
上调用dismissViewControllerAnimated...
而不是self
。
@rmaddy 已经尝试过了。同样的事情也会发生。
这是 iPad 还是 iPhone 上的问题?
@rmaddy iPad。没有在 iPhone 上试用,因为它是 iPad 专用的应用程序。我更改了标签以显示这一点。
在你的代码中,self
嵌入了什么?拆分视图控制器?标签栏控制器?尝试从应用的根视图控制器呈现图像选择器。
【参考方案1】:
我在 iOS7 下也遇到过同样的问题,我找到的唯一解决方案如下;
当你的 VC 展示选择器时;
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];
[self addChildViewController:picker] ;
[picker didMoveToParentViewController:self] ;
[self.view addSubview:picker.view] ;
然后,在处理选择器代表时 - 使用 ; 而不是dismissModal
[picker.view removeFromSuperview] ;
[picker removeFromParentViewController] ;
你失去的只是动画礼物/解雇 - 除此之外,一切都应该很好。
【讨论】:
有人能解释一下为什么上面的代码在8.1中可以工作,为什么不能正常工作 【参考方案2】:尝试将图像选择器的.modalPresentationStyle
设置为.OverCurrentContext
或.OverFullScreen
:
交替:
viewController.definesPresentationContext = true
imagePicker.modalPresentationStyle = .CurrentContext OR .FullScreen
关键是这两个属性之间的关系需要保持如下:如果false
然后.OverCurrentContext
,如果true
然后.CurrentContext
就我而言,我的视图控制器的.definesPresentationContext
默认为false,所以我使用了第一个选项。
See documentation for some insight.
【讨论】:
【参考方案3】:您应该关闭 选择器,而不是您的视图(自己) 并确保添加这些:
<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.imageView.image = chosenImage;
[picker dismissViewControllerAnimated:YES completion:NULL];
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
[picker dismissViewControllerAnimated:YES completion:NULL];
【讨论】:
【参考方案4】:当 UIImagePickerController 正式关闭时,它会在导航堆栈中紧随其后的任何 VC 上触发以下方法:
- viewWillAppear
- viewDidAppear
- viewDidLayoutSubviews
a bunch of other methods having to do with basic VC lifecycle.
就我而言,我并没有使用presentViewController:
方法展示最顶层的VC。我将它实例化为根 VC 的子级并做一些自定义动画。我在-viewDidLayoutSubviews
方法中完成了大部分工作。这项工作的一部分是指定我的子视图的框架处于屏幕外位置。
因此,当我在屏幕上设置子视图的动画,呈现相机,然后关闭它时,该应用最终触发了我的 rootVC 上的 -viewDidLayoutSubviews
,这将我的 childVC 移出了屏幕。
所以,我想答案是确保初始 VC 设置代码只能触发一次(在布置所有内容之前使用 Bool setupHasAlreadyHappenedOnce
之类的东西)。
【讨论】:
【参考方案5】:建议您在像这样将相机胶卷打开到 iPad 时使用 UIPopOver 所以试试吧,希望对你有帮助。
#pragma mark
#pragma mark - Image Picker
-(IBAction)onClickTakePhoto:(id)sender
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:imagePickerController.sourceType];
imagePickerController.allowsEditing = YES;
if ([self respondsToSelector:@selector(presentViewController:animated:completion:)])
[self presentViewController:imagePickerController animated:YES completion:nil];
else
[self presentModalViewController:imagePickerController animated:YES];
[imagePickerController release];
-(IBAction)onClickChooseFromLibrary:(id)sender
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum])
imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePickerController.delegate = self;
imagePickerController.allowsEditing = YES;
imagePickerController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:imagePickerController.sourceType];
popoverController= [[UIPopoverController alloc]
initWithContentViewController:imagePickerController];
[popoverController presentPopoverFromRect:btnLibrary.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
#pragma mark
#pragma mark - UIImagePickerDelegate
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
if ([self respondsToSelector:@selector(dismissViewControllerAnimated:completion:)])
[self dismissViewControllerAnimated:YES completion:nil];
else
[self dismissModalViewControllerAnimated:YES];
[popoverController dismissPopoverAnimated:YES];
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
if ([self respondsToSelector:@selector(dismissViewControllerAnimated:completion:)])
[self dismissViewControllerAnimated:YES completion:nil];
else
[self dismissModalViewControllerAnimated:YES];
[popoverController dismissPopoverAnimated:YES];
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
[userImage setLocalImage:image];
【讨论】:
您好,谢谢您的回答。在使用 iOS 6 时,我实际上使用了 PopOver,但从 iOS 7 开始,在 PopOver 中使用时,相机显示旋转 90 度。甚至 Apple 也建议不要再使用弹出框了。您可以在此答案中查看有关此的更多信息:***.com/a/19030558/517688 @Jan :如果你能看到那篇文章和我的回答都是一样的,他说如果你使用相机作为源类型,然后在presentModalViewController
上显示它,但如果你正在选择图像然后在 PopOver 中打开它,这样我的代码正在做同样的事情看看,然后尝试一次可能会解决您的问题 :)
presentModalViewController
在 iOS6 中已被弃用,所以我在我的代码中添加了条件,它根据条件使用。
没错,因为它已被弃用,而且我已经在使用 iOS7,所以最好不要使用它。如果我使用你的代码,作为 iOS7 respondsToSelector:@selector(presentViewController:animated:completion:)
我又遇到了我在问题中描述的问题。【参考方案6】:
当我试图从 UIContainerView 中呈现 UIImagePickerController 时,我遇到了类似但不完全的问题。
问题是解除 UIImagePickerController 改变了 UIContainerView 中的导航(调整为全屏)。
解决方案是从 UIContainerView 的父视图控制器中呈现 UIImagePickerController,现在一切正常。
【讨论】:
【参考方案7】:请注意,UIImagePickerController 的委托是“双重委托”,它也委托 UINavigationControllerDelegate。请参阅下面的代码。
@property(nullable,nonatomic,weak) id <UINavigationControllerDelegate, UIImagePickerControllerDelegate> delegate;
所以,检查self
是否也实现UINavigationControllerDelegate
,并像下面这样关闭父视图控制器。
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
NSMutableArray *stack = [navigationController.viewControllers mutableCopy];
if (stack.count >= 2)
[stack removeObjectAtIndex:(stack.count-2)];
navigationController.viewControllers = [stack copy];
navigationController.delegate = nil;
好的,我做到了,但我花了很多时间才知道。我的情况可能并不常见。仅供参考。
【讨论】:
以上是关于关闭 UIImagePickerController 也会使父级消失的主要内容,如果未能解决你的问题,请参考以下文章
ViewController 生命周期 UINavigationController
如何从 webview 使用 UIImagePickerController
iPhone OS 3.0 中的 UIImagePickerController