Swift 5.0 or above
1. Define variable declaration and outlets.
//#MARK: - Outlets
@IBOutlet weak var camPreview: UIView!
let minimumZoom: CGFloat = 1.0
let maximumZoom: CGFloat = 2.0
var lastZoomFactor: CGFloat = 1.0
var newCamera: AVCaptureDevice?
2. Get camera position and pinch gesture on Camera View.
//#MARK: - Views methods
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
newCamera = cameraWithPosition(position: .back)
//Add Pinch Gesture on CameraView.
let pinchRecognizer = UIPinchGestureRecognizer(target: self, action:#selector(pinch(_:)))
self.camPreview.addGestureRecognizer(pinchRecognizer)
}
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
func cameraWithPosition(position: AVCaptureDevice.Position) -> AVCaptureDevice? {
let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .unspecified)
for device in discoverySession.devices {
if device.position == position {
return device
}
}
return nil
}
3. Pinch-action with zoom-in and zoom out functionality.
@objc func pinch(_ pinch: UIPinchGestureRecognizer) {
guard let device = newCamera else { return }
// Return zoom value between the minimum and maximum zoom values
func minMaxZoom(_ factor: CGFloat) -> CGFloat {
return min(min(max(factor, minimumZoom), maximumZoom), device.activeFormat.videoMaxZoomFactor)
}
func update(scale factor: CGFloat) {
do {
try device.lockForConfiguration()
defer { device.unlockForConfiguration() }
device.videoZoomFactor = factor
} catch {
print("\(error.localizedDescription)")
}
}
let newScaleFactor = minMaxZoom(pinch.scale * lastZoomFactor)
switch pinch.state {
case .began: fallthrough
case .changed: update(scale: newScaleFactor)
case .ended:
lastZoomFactor = minMaxZoom(newScaleFactor)
update(scale: lastZoomFactor)
default: break
}
}
}