关闭 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

iOS开发——打开手机相册,获取图片

如何使用 iphone 中的核心数据将图像存储到 sqlite? [复制]

JFrame关闭方法的问题