项目中需要打开相机不停拍照,直到用户点击返回才结束,第三方框架都不满足需求,就只能自己动手做了。简单记录下关键部分,至于界面的自定义就不做介绍了。
1、初始化摄像头
func initCamera() {
if #available(iOS 10.0, *) {
self.captureDevice = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera, for: AVMediaType.video, position: self.positon)
} else {
self.captureDevice = AVCaptureDevice.default(for: AVMediaType.video)
}
try! self.captureDevice.lockForConfiguration()
if self.captureDevice.isFocusModeSupported(.autoFocus) {
self.captureDevice.focusMode = .autoFocus
}
self.captureDevice.unlockForConfiguration()
let input:AVCaptureDeviceInput
do {
input = try AVCaptureDeviceInput(device: self.captureDevice)
}catch{
self.showWithError(message: "处理输入源失败")
return
}
self.captureDeviceInput = input
if captureSession.canAddInput(self.captureDeviceInput) {
self.captureSession.addInput(self.captureDeviceInput)
}
if #available(iOS 10.0, *) {
let output:AVCapturePhotoOutput = AVCapturePhotoOutput()
output.isHighResolutionCaptureEnabled = true
self.photoOutput = output
} else {
// Fallback on earlier versions
let output:AVCaptureStillImageOutput = AVCaptureStillImageOutput()
output.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]
self.photoOutput = output
}
if captureSession.canAddOutput(photoOutput){
self.captureSession.addOutput(photoOutput)
}
let layer = AVCaptureVideoPreviewLayer(session: captureSession)
layer.videoGravity = AVLayerVideoGravity.resizeAspectFill
layer.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
layer.frame = self.cameraView.layer.bounds
self.cameraView.layer.insertSublayer(layer, at: 1)
}
2、点击拍照按钮进行拍照
@objc func startTakePhoto() {
if #available(iOS 10.0, *) {
let photoSettings = AVCapturePhotoSettings()
photoSettings.isAutoStillImageStabilizationEnabled = true
photoSettings.isHighResolutionPhotoEnabled = true
photoSettings.flashMode = self.flashMode
let output:AVCapturePhotoOutput = (self.photoOutput as! AVCapturePhotoOutput)
output.capturePhoto(with: photoSettings, delegate: self)
} else {
let output:AVCaptureStillImageOutput = (self.photoOutput as! AVCaptureStillImageOutput)
let videoConnection:AVCaptureConnection? = output.connection(with: AVMediaType.video)
if videoConnection == nil {
return
}
output.captureStillImageAsynchronously(from: videoConnection!) { (imageDataSampleBuffer, error) in
if imageDataSampleBuffer == nil {
return
}
let imageData:Data = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer!)!
self.takePhotoResult(imageData: imageData)
}
}
}
此处需要注意,ios10及以上系统需要实现代理来获取拍照内容
AVCapturePhotoCaptureDelegate代理实现如下
@available(iOS 10.0, *)
extension TakePhotoVC:AVCapturePhotoCaptureDelegate {
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {
if photoSampleBuffer == nil {
return
}
let imageData:Data? = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer!, previewPhotoSampleBuffer: previewPhotoSampleBuffer)
self.takePhotoResult(imageData: imageData)
}
}
3、获取拍照结果
func takePhotoResult(imageData:Data?) {
if imageData == nil {
return
}
let image = UIImage(data: imageData!)
if image == nil {
return
}
self.imageArray.append(image!)
self.reloadImageView()
//压缩图片
let imageTemp = image!.wxCompress()
//给图片打水印
let waterImage = BsUtils.textWaterImage(image: imageTemp, text: DateUtil.getDateFormatter(date: Date(), format: "yyyy-MM-dd HH:mm"))
if waterImage == nil {
return
}
let imagePath = FileHelper.saveImage(tempImage: waterImage!, imageName: "\(UUID().uuidString).jpg", dirName: AppConfig.upload_file_dir, isCompression: false)
self.didFinishCapturePhotoOnce?(imageTemp,imagePath ?? "")
}
4、打开或关闭手电筒
@objc func torchBtnClick(button:UIButton) {
if button.tag == 1 {
//开启电筒
if !self.captureDevice.isTorchModeSupported(.on){
return
}
self.torchMode = .on
}else{
if !self.captureDevice.isTorchModeSupported(.off){
return
}
//关闭电筒
self.torchMode = .off
button.tag = 1
}
self.updateDeviceTorchMode()
}
func updateDeviceTorchMode() {
try! self.captureDevice.lockForConfiguration()
if self.captureDevice.isTorchModeSupported(self.torchMode) {
self.captureDevice?.torchMode = self.torchMode
}
self.captureDevice.unlockForConfiguration()
}