相机切换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//前后摄像头的切换
- (void)changeDeviceAction
{
    [self.session beginConfiguration];
    //改变会话的配置前一定要先开启配置,配置完成后提交配置改变
    AVCaptureDevice *currentDevice = [self.imageInput device];
    AVCaptureDevice *toChangeDevice;
    if([currentDevice position] == AVCaptureDevicePositionBack){
        toChangeDevice = [self cameraWithPosition:AVCaptureDevicePositionFront];
    }else{
        toChangeDevice = [self cameraWithPosition:AVCaptureDevicePositionBack];
    }
    //获得要调整的设备输入对象

    AVCaptureDeviceInput *toChangeDeviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:toChangeDevice error:nil];
    //移除原有输入对象
    [self.session removeInput:self.imageInput];
    //添加新的输入对象
    if ([self.session canAddInput:toChangeDeviceInput]) {
        [self.session addInput:toChangeDeviceInput];
        self.imageInput = toChangeDeviceInput;
    }
    //提交会话配置
    [self.session commitConfiguration];
}
//定向获取摄像头设备
- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position
{
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

    for (AVCaptureDevice *device in devices)
    {
        if ([device position] == position)
            return device;
    }
    return nil;
}

问题

控制摄像机 AVCaptureSession 运行状态

  1. 初始化session

    1
    2
    
       //负责输入和输出设备之间的数据传递
       @property(nonatomic)AVCaptureSession *session;
  2. 当页面加载完成时,激活session:startRunning

    1
    2
    3
    4
    5
    
       -(void)viewDidAppear:(BOOL)animated
       {
           [super viewDidAppear:animated];
           [self.session startRunning];
       }
  3. 当页面消失时,停止session

    1
    2
    3
    4
    
       -(void)viewDidDisappear:(BOOL)animated{
           [super viewDidDisappear:animated];
           [self.session stopRunning];
       }

上述代码,看似没有问题,但是放在以下场景中,会导致无法正常切换摄像头。

场景描述:有两个拍照页面,先使用后置摄像头,拍环境照片,然后进入预览页面。再返回拍照页面,切换前置摄像头,进行正面拍照。这时,会出现无法切换摄像头的问题。

问题分析:在当第一次拍照进入上传页面时,会 stopRunning 停止,这时如果在上传页面完成上传时,执行拍照的页面的带代理方法时,~session~ 还是stop 状态,无法进行切换摄像头。

解决思路:要在激活 session 才能进行摄像头切换。

这样,需要在 viewDidAppear 方法中,确定执行 startRunning 之后,再执行摄像头切换:如:7-9 行代码。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    if (!self.session.running) {
        [self.session startRunning];
        //切换摄像头
        if (self.style == 1) {
            [self changeDeviceAction];
        }
    }
}