我试图在我的应用上创建自定义相机。这很简单,我想拍照并将拍摄的图像发送到下一个视图控制器。但是,我不知道为什么,但是当我用前置摄像头拍照时相机还可以,但是当它是后置摄像头时,它不是。
当我按下按钮捕捉照片时,可能会有7秒的延迟,而且应用程序会在两次中崩溃一次。
这是我的代码:
var captureSession = AVCaptureSession()
var backCamera: AVCaptureDevice?
var frontCamera: AVCaptureDevice?
var currentCamera: AVCaptureDevice?
var photoOutput: AVCapturePhotoOutput?
var cameraPreviewLayer: AVCaptureVideoPreviewLayer?
var image: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
setupCaptureSession()
setupDevice()
setupInputOutput()
setupPreviewLayer()
startRunningCaptureSession()
}
func setupCaptureSession(){
captureSession.sessionPreset = AVCaptureSession.Preset.photo
}
func setupDevice(){
let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: .video, position: AVCaptureDevice.Position.unspecified)
let devices = deviceDiscoverySession.devices
for device in devices {
if device.position == AVCaptureDevice.Position.back {
backCamera = device
} else if device.position == AVCaptureDevice.Position.front {
frontCamera = device
}
}
currentCamera = backCamera
}
func setupInputOutput(){
do {
let captureDeviceInput = try AVCaptureDeviceInput(device: currentCamera!)
captureSession.addInput(captureDeviceInput)
photoOutput = AVCapturePhotoOutput()
if #available(iOS 11.0, *) {
photoOutput?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)
} else {
// Fallback on earlier versions
photoOutput?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecJPEG])], completionHandler: nil)
}
captureSession.addOutput(photoOutput!)
} catch {
print(error)
}
}
func setupPreviewLayer(){
cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
cameraPreviewLayer?.frame = CGRect(x: 0, y: 0, width: self.cameraView.frame.size.width, height: self.cameraView.frame.size.height)
cameraView.layer.addSublayer(cameraPreviewLayer!)
//self.view.layer.insertSublayer(cameraPreviewLayer!, at: 0)
}
func startRunningCaptureSession(){
captureSession.startRunning()
}
@IBAction func switchCameraAction(_ sender: Any) {
swapCamera()
}
/// Swap camera and reconfigures camera session with new input
fileprivate func swapCamera() {
// Get current input
guard let input = captureSession.inputs[0] as? AVCaptureDeviceInput else { return }
// Begin new session configuration and defer commit
captureSession.beginConfiguration()
defer { captureSession.commitConfiguration() }
// Create new capture device
var newDevice: AVCaptureDevice?
if input.device.position == .back {
newDevice = captureDevice(with: .front)
isFront = true
} else {
newDevice = captureDevice(with: .back)
isFront = false
}
// Create new capture input
var deviceInput: AVCaptureDeviceInput!
do {
deviceInput = try AVCaptureDeviceInput(device: newDevice!)
} catch let error {
print(error.localizedDescription)
return
}
// Swap capture device inputs
captureSession.removeInput(input)
captureSession.addInput(deviceInput)
}
fileprivate func captureDevice(with position: AVCaptureDevice.Position) -> AVCaptureDevice? {
let devices = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: .video, position: AVCaptureDevice.Position.unspecified).devices
for device in devices {
if device.position == position {
return device
}
}
return nil
}
func crop(_ image: UIImage, withWidth width: Double, andHeight height: Double) -> UIImage? {
if let cgImage = image.cgImage {
let contextImage: UIImage = UIImage(cgImage: cgImage)
let contextSize: CGSize = contextImage.size
var posX: CGFloat = 0.0
var posY: CGFloat = 0.0
var cgwidth: CGFloat = CGFloat(width)
var cgheight: CGFloat = CGFloat(height)
// See what size is longer and create the center off of that
if contextSize.width > contextSize.height {
posX = ((contextSize.width - contextSize.height) / 2)
posY = 0
cgwidth = contextSize.height
cgheight = contextSize.height
} else {
posX = 0
posY = ((contextSize.height - contextSize.width) / 2)
cgwidth = contextSize.width
cgheight = contextSize.width
}
let rect: CGRect = CGRect(x: posX, y: posY, width: cgwidth, height: cgheight)
// Create bitmap image from context using the rect
var croppedContextImage: CGImage? = nil
if let contextImage = contextImage.cgImage {
if let croppedImage = contextImage.cropping(to: rect) {
croppedContextImage = croppedImage
}
}
// Create a new image based on the imageRef and rotate back to the original orientation
if let croppedImage:CGImage = croppedContextImage {
let image: UIImage = UIImage(cgImage: croppedImage, scale: image.scale, orientation: image.imageOrientation)
return image
}
}
return nil
}
@IBAction func takePhotoAction(_ sender: Any) {
var settingsCamera = AVCapturePhotoSettings()
let previewPixelType = settingsCamera.availablePreviewPhotoPixelFormatTypes.first
settingsCamera.flashMode = .off
if isFront == false && hasFlash{
settingsCamera.flashMode = .on
}
let previewFormat = [kCVPixelBufferPixelFormatTypeKey as String: previewPixelType,
kCVPixelBufferWidthKey as String: 160,
kCVPixelBufferHeightKey as String: 160]
settingsCamera.previewPhotoFormat = previewFormat
photoOutput?.capturePhoto(with: settingsCamera, delegate: self)
}
}
extension UploadViewController: AVCapturePhotoCaptureDelegate {
func photoOutput(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {
if let error = error {
print("error occure : \(error.localizedDescription)")
}
if let sampleBuffer = photoSampleBuffer,
let previewBuffer = previewPhotoSampleBuffer,
let dataImage = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: previewBuffer) {
let dataProvider = CGDataProvider(data: dataImage as CFData)
let cgImageRef: CGImage! = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: .defaultIntent)
var orientation = UIImageOrientation(rawValue: 0)
if isFront {
orientation = UIImageOrientation.leftMirrored
} else {
orientation = UIImageOrientation.right
}
let image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: orientation!)
// var flippedImage = UIImage(CGImage: picture.CGImage!, scale: picture.scale, orientation: .leftMirrored)
let timage = crop(image, withWidth: 100, andHeight: 100)
let photoSecondVC = self.storyboard?.instantiateViewController(withIdentifier: "uploadSecondVC") as! UploadSecondViewController
photoSecondVC.imageData = timage!
photoSecondVC.isFront = isFront
self.navigationController?.pushViewController(photoSecondVC, animated: false)
} else {
print("some error here")
}
}
}
这是应用程序崩溃时的情况(我不知道是否有链接):
2017-08-25 16:50:36.125052 + 0200 Fitshare [93231:3349636]无法在(UITabBarItem)上设置(keyPath)用户定义的检查属性:[setValue:forUndefinedKey:]:此类不是键值编码 - 适用于密钥keyPath。 2017-08-25 16:50:36.125584 + 0200 Fitshare [93231:3349636]无法在(UITabBarItem)上设置(keyPath)用户定义的检查属性:[setValue:forUndefinedKey:]:此类不符合键值编码关键keyPath。 2017-08-25 16:50:36.300650 + 0200 Fitshare [93231:3349636] [MC]懒加载NSBundle MobileCoreServices.framework 2017-08-25 16:50:36.302462 + 0200 Fitshare [93231:3349636] [MC]已加载MobileCoreServices.framework 2017-08-25 16:50:36.311211 + 0200 Fitshare [93231:3349636] [MC] systemgroup.com.apple.configurationprofiles路径的系统组容器是/ Users / kevinboirel / Library / Developer / CoreSimulator / Devices / B48E7503-47C0 -4A75-AC5C-C3DEF6CC8507 /数据/容器/共享/ SystemGroup / systemgroup.com.apple.configurationprofiles 2017-08-25 16:50:36.363022 + 0200 Fitshare [93231:3349636] [Snapshotting]快照至少一次渲染的视图(0x7fbb38f2b0c0,Fitshare.ALThreeCircleSpinner)需要afterScreenUpdates:YES。 2017-08-25 16:50:36.469416 + 0200 Fitshare [93231:3349636] + [CATransaction synchronize]在交易中调用 2017-08-25 16:50:36.469800 + 0200 Fitshare [93231:3349636] + [CATransaction synchronize]在交易中调用
奇怪的事实是我在XCode中有这个消息错误:
答案 0 :(得分:1)
您需要两个协议代理,分别是:UIImagePickerControllerDelegate
和UINavigationControllerDelegate
// MARK: - Global Declaration
@IBOutlet var imgProfile: UIImageView!
var imagePicker = UIImagePickerController()
// MARK: - Camera Methods
func PickingImageFromCamera()
{
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = false
picker.sourceType = .camera
picker.cameraCaptureMode = .photo
present(picker, animated: true, completion: nil)
}
//----------------------------------
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String : Any])
{
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imgProfile.contentMode = .scaleToFill
imgProfile.image = pickedImage
}
dismiss(animated: true, completion: nil)
}
//----------------------------------
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
//----------------------------------
我认为此代码可以帮助您......
答案 1 :(得分:0)
这是由于UploadSecondViewController ...
我只是将发送到第二个ViewController的图片调整为更小的尺寸,现在应用程序已经确定了!
感谢您的回答!