简体   繁体   English

在打开的相机上呈现相机胶卷UIImagePickerController

[英]Presenting camera roll UIImagePickerController over open camera

On my app I have a cameraOverlayView over my open camera with custom controls for the camera buttons. 在我的应用程序上,我在我的打开相机上有一个cameraOverlayView ,带有相机按钮的自定义控件。 The app allows the user to take several pictures before closing the camera, so the shutter button does not call dismissViewControllerAnimated , instead there's a close button for when you're done taking pictures. 该应用程序允许用户在关闭相机之前拍摄多张照片,因此快门按钮不会调用dismissViewControllerAnimated ,而是有一个关闭按钮,用于拍摄照片。

Now, one of the buttons on the camera overlay is a gallery button to allow the user to pick a saved image instead of shooting a new one. 现在,相机覆盖图上的一个按钮是一个图库按钮,允许用户选择保存的图像而不是拍摄新的图像。 I've tried two different approaches to make this work, both failed. 我尝试了两种不同的方法来完成这项工作,但都失败了。

First approach 第一种方法

Use the same UIImagePickerController instance that is currently presenting the overlay and switch the sourceType to library. 使用当前呈现覆盖的相同UIImagePickerController实例并将sourceType切换到库。 It does present the gallery then, but when a photo is tapped, I can't dismiss the galley without dismissing the whole overlay. 它确实呈现了画廊,但是当拍摄照片时,我不能在不解雇整个叠加层的情况下解雇厨房。

Second approach 第二种方法

Create a separate instance of UIImagePickerController , set the sourceType to gallery and attempt to call presentViewController , which then fails with the warning: 创建一个单独的UIImagePickerController实例,将sourceType设置为gallery并尝试调用presentViewController ,然后使用警告失败:

"Warning: Attempt to present on whose view is not in the window hierarchy!" “警告:尝试在窗口层次结构中显示其视图!”

Does anyone have a solution for this issue? 有没有人有这个问题的解决方案? Is this even possible? 这甚至可能吗?

Try this~~ I think it is your goal. 试试这个~~我认为这是你的目标。

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) UIImagePickerController *imagePicker;

@end

@implementation ViewController

@synthesize imagePicker = _imagePicker;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

}


- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:YES];

    sleep(2);

    _imagePicker = [[UIImagePickerController alloc] init];
    [_imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
    [_imagePicker setDelegate:self];

    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 50, 100, 30)];
    [button setTitle:@"Library" forState:UIControlStateNormal];
    [button setBackgroundColor:[UIColor darkGrayColor]];
    [button addTarget:self action:@selector(gotoLibrary:) forControlEvents:UIControlEventTouchUpInside];

    [_imagePicker.view addSubview:button];

    [self presentViewController:_imagePicker animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(IBAction)gotoLibrary:(id)sender
{
    UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
    [imagePicker.view setFrame:CGRectMake(0, 80, 320, 350)];
    [imagePicker setSourceType:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
    [imagePicker setDelegate:self];

    [_imagePicker presentViewController:imagePicker animated:YES completion:nil];
}


- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [picker dismissViewControllerAnimated:YES completion:nil];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [picker dismissViewControllerAnimated:YES completion:nil];
}
@end

The second approach is correct. 第二种方法是正确的。 I don't see your code, but I think that your controller hierarchy is something similar to this: 我没有看到你的代码,但我认为你的控制器层次结构类似于:

Main VC ---present---> Camera VC 主VC ---现在--->相机VC

so, if you call 所以,如果你打电话

[self presentViewController:picker animated:YES completion:^{}];

from your Main VC, you are attempting to show another VC from an "hidden" one (covered by the Camera VC). 在您的主VC中,您试图从“隐藏”VC中显示另一个VC(由Camera VC覆盖)。

The key is to take a reference to your camera VC (let's call it cameraVC) and do something similar from Main VC: 关键是要参考你的相机VC(我们称之为cameraVC)并从主VC做类似的事情:

 [cameraVC presentViewController:theOtherPicker animated:YES completion:^{}];

doing this, the "present" action is done by the Camera VC (visible) without warnings, and not by the hidden Main VC. 这样做,“当前”动作由Camera VC(可见)完成而没有警告,而不是由隐藏的主VC完成。

You could code your own custom gallery views for selecting photos and then add that to the cameraOverlayView subview hierarchy. 您可以编写自己的自定义图库视图以选择照片,然后将其添加到cameraOverlayView子视图层次结构中。

There must be open source projects on GitHub, which show how to make these views, somewhere. GitHub上必须有开源项目,它们展示了如何在某个地方创建这些视图。 Alternatively, I happen to have released a control very similar to what you are looking for if you don't want to start from scratch. 或者,如果你不想从头开始,我碰巧发布了一个与你正在寻找的非常相似的控件

It's quite a simple procedure really — a collection view with a datasource backed by the AssetsLibrary framework. 这真的是一个非常简单的过程 - 一个带有AssetsLibrary框架支持的数据源的集合视图。

I would set up a capture session as follows: 我会建立一个捕获会话如下:

- (void)setupCaptureSession
{
    NSError* error = nil;

    // Create the session
    _captureSession = [[AVCaptureSession alloc] init];    
    _captureSession.sessionPreset = AVCaptureSessionPresetMedium;
    AVCaptureDevice* device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];

    [_captureSession addInput:input];
    AVCaptureVideoDataOutput* output = [[AVCaptureVideoDataOutput alloc] init];
    [_captureSession addOutput:output];

    // Configure your output.
   dispatch_queue_t queue = dispatch_queue_create("myCameraOutputQueue", NULL);
   //If you want to sebsequently use the data, then implement the delegate.
   [output setSampleBufferDelegate:self queue:queue]; 
}

Having done that, you can create a preview layer as follows: 完成后,您可以按如下方式创建预览图层:

_previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_captureSession];
[_captureSession startRunning];

And then add the preview layer to your view: 然后将预览图层添加到视图中:

_myView.layer addSubLayer:_previewLayer];

Now that you have this set up, I'd add a custom image picker, such as this one: https://github.com/arturgrigor/AGImagePickerController 现在您已经设置了这个,我将添加一个自定义图像选择器,例如: https//github.com/arturgrigor/AGImagePickerController

I present a custom camera view controller, onto which I add a "SourceTypeCamera" UIImagePickerController as a contained child view controller. 我提出了一个自定义的摄像机视图控制器,我在其上添加了一个“SourceTypeCamera”UIImagePickerController作为包含的子视图控制器。 My custom view controller has a button that in turn adds another UIImagePickerController instance, this one a "SourceTypePhotoLibrary". 我的自定义视图控制器有一个按钮,该按钮又添加了另一个UIImagePickerController实例,这个实例是一个“SourceTypePhotoLibrary”。

You end up with a nested view controller hierarchy: 您最终得到一个嵌套的视图控制器层次结构:

  • root/main view controller — presents: 根/主视图控制器- 呈现:
  • my custom camera view controller – adds as child view controller: 我的自定义相机视图控制器- 添加为子视图控制器:
  • either camera or photo-library UIImagePickerController 无论是相机照片库中的UIImagePickerController

Something like this: 像这样的东西:

- (void)viewDidLoad { (id<UIImagePickerControllerDelegate,UINavigationControllerDelegate>)theDelegate {
    [super viewDidLoad];
    [self startImagePickerWithSourceType:UIImagePickerControllerSourceTypeCamera
                                delegate:self];
    // configure button in camera overlay to call -pickPhotoTapped
}

- (void) pickPhotoTapped {
    [self startImagePickerWithSourceType:UIImagePickerControllerSourceTypePhotoLibrary
                                delegate:self];
}

- (BOOL) startImagePickerWithSourceType:(UIImagePickerControllerSourceType)sourceType
                               delegate:(id<UIImagePickerControllerDelegate,UINavigationControllerDelegate>)theDelegate {
    if (([UIImagePickerController isSourceTypeAvailable:sourceType] == NO)
            || (theDelegate == nil))
        return NO;

    self.cameraUI = [[UIImagePickerController alloc] init];
    self.cameraUI.sourceType = sourceType;
    self.cameraUI.view.frame = self.view.bounds;
    self.cameraUI.delegate = theDelegate;

    if (sourceType == UIImagePickerControllerSourceTypeCamera) {
        self.cameraUI.allowsEditing = NO;
        self.cameraUI.showsCameraControls = NO;
        self.cameraUI.cameraOverlayView = [self overlayView];
    }

    [self addChildViewController:self.cameraUI];
    [self.view addSubview:self.cameraUI.view];
    [self.cameraUI didMoveToParentViewController:self];

    return YES;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM