用零碎自带的视听媒体的框架,AVFoundation实现照片拍摄。相比UIKit框架(UIImagePickerController高度封装),AVFoundation框架让开发者有更大的施展空间。

首先看一下效果图:
上面贴上外围控制器代码:

#import "HWPhotoVC.h"#import <AVFoundation/AVFoundation.h> @interface HWPhotoVC () @property (nonatomic, strong) AVCaptureSession *captureSession;//负责输出和输出设备之间的数据传递@property (nonatomic, strong) AVCaptureDeviceInput *captureDeviceInput;//负责从AVCaptureDevice取得输出数据@property (nonatomic, strong) AVCaptureStillImageOutput *captureStillImageOutput;//照片输入流@property (nonatomic, strong) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer;//相机拍摄预览图层@property (nonatomic, weak) UIView *containerView;//内容视图@property (nonatomic, weak) UIImageView *focusCursor;//聚焦按钮@property (nonatomic, weak) UIImageView *imgView;//拍摄照片 @end @implementation HWPhotoVC - (void)viewDidLoad { [super viewDidLoad];  self.navigationItem.title = @"拍照"; self.view.backgroundColor = [UIColor whiteColor];  //创立控件 [self creatControl];} - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated];  //初始化信息 [self initPhotoInfo];} - (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated];  [self.captureSession startRunning];} - (void)viewDidDisappear:(BOOL)animated{ [super viewDidDisappear:animated];  [self.captureSession stopRunning];} - (void)creatControl{ CGFloat btnW = 150.f; CGFloat btnH = 40.f; CGFloat marginY = 20.f; CGFloat w = [UIScreen mainScreen].bounds.size.width; CGFloat h = [UIScreen mainScreen].bounds.size.height;  //内容视图 CGFloat containerViewH = h - 64 - btnH - marginY * 3; UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(10, 64 + marginY, w - 20, containerViewH)]; containerView.backgroundColor = [UIColor whiteColor]; containerView.layer.borderWidth = 1.f; containerView.layer.borderColor = [[UIColor grayColor] CGColor]; [self.view addSubview:containerView]; _containerView = containerView;  //摄像头切换按钮 CGFloat cameraSwitchBtnW = 50.f; CGFloat cameraSwitchBtnMargin = 10.f; UIButton *cameraSwitchBtn = [[UIButton alloc] initWithFrame:CGRectMake(containerView.bounds.size.width - cameraSwitchBtnW - cameraSwitchBtnMargin, 64 + marginY + cameraSwitchBtnMargin, cameraSwitchBtnW, cameraSwitchBtnW)]; [cameraSwitchBtn setImage:[UIImage imageNamed:@"camera_switch"] forState:UIControlStateNormal]; [cameraSwitchBtn addTarget:self action:@selector(cameraSwitchBtnOnClick) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:cameraSwitchBtn];  //聚焦图片 UIImageView *focusCursor = [[UIImageView alloc] initWithFrame:CGRectMake(50, 50, 75, 75)]; focusCursor.alpha = 0; focusCursor.image = [UIImage imageNamed:@"camera_focus_red"]; [containerView addSubview:focusCursor]; _focusCursor = focusCursor;  //拍摄照片容器 UIImageView *imgView = [[UIImageView alloc] initWithFrame:containerView.frame]; imgView.hidden = YES; imgView.layer.borderWidth = 1.f; imgView.layer.borderColor = [[UIColor grayColor] CGColor]; imgView.contentMode = UIViewContentModeScaleAspectFill; imgView.clipsToBounds = YES; [self.view addSubview:imgView]; _imgView = imgView;  //按钮 NSArray *titleArray = @[@"拍摄照片", @"从新拍摄"]; CGFloat btnY = CGRectGetMaxY(containerView.frame) + marginY; CGFloat margin = (w - btnW * titleArray.count) / (titleArray.count + 1); for (int i = 0; i < titleArray.count; i++) {  CGFloat btnX = margin + (margin + btnW) * i;  UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(btnX, btnY, btnW, btnH)];  btn.tag = 1000 + i;  [btn setTitle:titleArray[i] forState:UIControlStateNormal];  btn.backgroundColor = [UIColor orangeColor];  btn.layer.cornerRadius = 2.0f;  btn.layer.masksToBounds = YES;  if (i == 1) {   btn.hidden = YES;  }  [btn addTarget:self action:@selector(btnOnClick:) forControlEvents:UIControlEventTouchUpInside];  [self.view addSubview:btn]; }} - (void)initPhotoInfo{ //初始化会话 _captureSession = [[AVCaptureSession alloc] init];  //设置分辨率 if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {  _captureSession.sessionPreset = AVCaptureSessionPreset1280x720; }  //取得输出设施,获得后置摄像头 AVCaptureDevice *captureDevice = [self getCameraDeviceWithPosition:AVCaptureDevicePositionBack]; if (!captureDevice) {  NSLog(@"获得后置摄像头时呈现问题");  return; }  NSError *error = nil; //依据输出设施初始化设施输出对象,用于取得输出数据 _captureDeviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:captureDevice error:&error]; if (error) {  NSLog(@"获得设施输出对象时出错,谬误起因:%@", error.localizedDescription);  return; }  //初始化设施输入对象,用于取得输入数据 _captureStillImageOutput = [[AVCaptureStillImageOutput alloc] init]; NSDictionary *outputSettings = @{AVVideoCodecKey:AVVideoCodecJPEG}; //输入设置 [_captureStillImageOutput setOutputSettings:outputSettings];  //将设施输出增加到会话中 if ([_captureSession canAddInput:_captureDeviceInput]) {  [_captureSession addInput:_captureDeviceInput]; }  //将设施输入增加到会话中 if ([_captureSession canAddOutput:_captureStillImageOutput]) {  [_captureSession addOutput:_captureStillImageOutput]; }  //创立视频预览层,用于实时展现摄像头状态 _captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];  //摄像头方向 AVCaptureConnection *captureConnection = [self.captureVideoPreviewLayer connection]; captureConnection.videoOrientation = AVCaptureVideoOrientationPortrait;  CALayer *layer = _containerView.layer; layer.masksToBounds = YES;  _captureVideoPreviewLayer.frame = layer.bounds; //填充模式 _captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; //将视频预览层增加到界面中 [layer insertSublayer:_captureVideoPreviewLayer below:self.focusCursor.layer];  [self addNotificationToCaptureDevice:captureDevice]; [self addGenstureRecognizer];} - (void)btnOnClick:(UIButton *)btn{ if (btn.tag == 1000) {  //拍摄照片  [self photoBtnOnClick];  }else if (btn.tag == 1001) {  //从新拍摄  [self resetPhoto]; }} #pragma mark 拍照- (void)photoBtnOnClick{ //依据设施输入取得连贯 AVCaptureConnection *captureConnection = [self.captureStillImageOutput connectionWithMediaType:AVMediaTypeVideo]; captureConnection.videoOrientation = AVCaptureVideoOrientationPortrait;  //依据连贯获得设施输入的数据 [self.captureStillImageOutput captureStillImageAsynchronouslyFromConnection:captureConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {  if (imageDataSampleBuffer) {   NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];   UIImage *image = [UIImage imageWithData:imageData];   _imgView.image = image;   _imgView.hidden = NO;  } }];  UIButton *btn = (UIButton *)[self.view viewWithTag:1001]; btn.hidden = NO;} //从新拍摄- (void)resetPhoto{ _imgView.hidden = YES; UIButton *btn = (UIButton *)[self.view viewWithTag:1001]; btn.hidden = YES;} #pragma mark - 告诉//给输出设施增加告诉- (void)addNotificationToCaptureDevice:(AVCaptureDevice *)captureDevice{ //留神增加区域扭转捕捉告诉必须首先设置设施容许捕捉 [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  captureDevice.subjectAreaChangeMonitoringEnabled = YES; }];  //捕捉区域产生扭转 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(areaChange:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice];} - (void)removeNotificationFromCaptureDevice:(AVCaptureDevice *)captureDevice{ [[NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice];} //移除所有告诉- (void)removeNotification{ [[NSNotificationCenter defaultCenter] removeObserver:self];} //设施连贯胜利- (void)deviceConnected:(NSNotification *)notification{ NSLog(@"设施已连贯...");} //设施连贯断开- (void)deviceDisconnected:(NSNotification *)notification{ NSLog(@"设施已断开.");} //捕捉区域扭转- (void)areaChange:(NSNotification *)notification{ NSLog(@"捕捉区域扭转...");} #pragma mark - 公有办法//获得指定地位的摄像头- (AVCaptureDevice *)getCameraDeviceWithPosition:(AVCaptureDevicePosition )position{ NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; for (AVCaptureDevice *camera in cameras) {  if ([camera position] == position) {   return camera;  } }  return nil;} #pragma mark 切换前后摄像头- (void)cameraSwitchBtnOnClick{ AVCaptureDevice *currentDevice = [self.captureDeviceInput device]; AVCaptureDevicePosition currentPosition = [currentDevice position]; [self removeNotificationFromCaptureDevice:currentDevice];  AVCaptureDevice *toChangeDevice; AVCaptureDevicePosition toChangePosition = AVCaptureDevicePositionFront; if (currentPosition == AVCaptureDevicePositionUnspecified || currentPosition == AVCaptureDevicePositionFront) {  toChangePosition = AVCaptureDevicePositionBack; } toChangeDevice = [self getCameraDeviceWithPosition:toChangePosition]; [self addNotificationToCaptureDevice:toChangeDevice]; //取得要调整的设施输出对象 AVCaptureDeviceInput *toChangeDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:toChangeDevice error:nil];  //扭转会话的配置前肯定要先开启配置,配置实现后提交配置扭转 [self.captureSession beginConfiguration]; //移除原有输出对象 [self.captureSession removeInput:self.captureDeviceInput]; //增加新的输出对象 if ([self.captureSession canAddInput:toChangeDeviceInput]) {  [self.captureSession addInput:toChangeDeviceInput];  self.captureDeviceInput = toChangeDeviceInput; } //提交会话配置 [self.captureSession commitConfiguration];} //扭转设施属性的对立操作方法- (void)changeDeviceProperty:(void (^)(AVCaptureDevice *))propertyChange{ AVCaptureDevice *captureDevice = [self.captureDeviceInput device]; NSError *error; //留神扭转设施属性前肯定要首先调用lockForConfiguration:调用完之后应用unlockForConfiguration办法解锁 if ([captureDevice lockForConfiguration:&error]) {  propertyChange(captureDevice);  [captureDevice unlockForConfiguration];  }else {  NSLog(@"设置设施属性过程产生谬误,错误信息:%@", error.localizedDescription); }} //设置闪光灯模式- (void)setFlashMode:(AVCaptureFlashMode)flashMode{ [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  if ([captureDevice isFlashModeSupported:flashMode]) {   [captureDevice setFlashMode:flashMode];  } }];} //设置聚焦模式- (void)setFocusMode:(AVCaptureFocusMode)focusMode{ [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  if ([captureDevice isFocusModeSupported:focusMode]) {   [captureDevice setFocusMode:focusMode];  } }];} //设置曝光模式- (void)setExposureMode:(AVCaptureExposureMode)exposureMode{ [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  if ([captureDevice isExposureModeSupported:exposureMode]) {   [captureDevice setExposureMode:exposureMode];  } }];} //设置聚焦点- (void)focusWithMode:(AVCaptureFocusMode)focusMode exposureMode:(AVCaptureExposureMode)exposureMode atPoint:(CGPoint)point{ [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  if ([captureDevice isFocusModeSupported:focusMode]) {   [captureDevice setFocusMode:AVCaptureFocusModeAutoFocus];  }  if ([captureDevice isFocusPointOfInterestSupported]) {   [captureDevice setFocusPointOfInterest:point];  }  if ([captureDevice isExposureModeSupported:exposureMode]) {   [captureDevice setExposureMode:AVCaptureExposureModeAutoExpose];  }  if ([captureDevice isExposurePointOfInterestSupported]) {   [captureDevice setExposurePointOfInterest:point];  } }];} //增加点按手势,点按时聚焦- (void)addGenstureRecognizer{ [self.containerView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapScreen:)]];} - (void)tapScreen:(UITapGestureRecognizer *)tapGesture{ CGPoint point = [tapGesture locationInView:self.containerView]; //将UI坐标转化为摄像头坐标 CGPoint cameraPoint = [self.captureVideoPreviewLayer captureDevicePointOfInterestForPoint:point]; [self setFocusCursorWithPoint:point]; [self focusWithMode:AVCaptureFocusModeAutoFocus exposureMode:AVCaptureExposureModeAutoExpose atPoint:cameraPoint];} //设置聚焦光标地位- (void)setFocusCursorWithPoint:(CGPoint)point{ self.focusCursor.center = point; self.focusCursor.transform = CGAffineTransformMakeScale(1.5, 1.5); self.focusCursor.alpha = 1.0; [UIView animateWithDuration:1.0 animations:^{  self.focusCursor.transform = CGAffineTransformIdentity; } completion:^(BOOL finished) {  self.focusCursor.alpha = 0; }];} - (void)dealloc{ [self removeNotification];} @end

Demo下载链接

以上就是本文的全部内容,心愿对大家的学习有所帮忙