Skip to content

Commit

Permalink
Merge pull request #56 from clutter/ksylvest/support-camera-view-in-s…
Browse files Browse the repository at this point in the history
…imulator

Support Camera View in Simulator
  • Loading branch information
ksylvest authored Apr 5, 2022
2 parents 26b383d + a12be14 commit 6a865b8
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 45 deletions.
10 changes: 5 additions & 5 deletions Example/PodApp/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
PODS:
- SwiftLint (0.34.0)
- TiltUp (2.8.1)
- TiltUpTest (2.8.1):
- TiltUp (= 2.8.1)
- TiltUp (3.1.0)
- TiltUpTest (3.1.0):
- TiltUp (= 3.1.0)

DEPENDENCIES:
- SwiftLint
Expand All @@ -21,8 +21,8 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
SwiftLint: 79d48a17c6565dc286c37efb8322c7b450f95c67
TiltUp: 1faef29c73efea74f261ceedc24bcc620d48f96f
TiltUpTest: 54580c30690a13200352ca0eca275bc5ed2f7408
TiltUp: 43e69ef22cdba68167a0b4380fc91ed6a741c90a
TiltUpTest: be361829df0ae5a2b6a8548f90587bc08fbc119e

PODFILE CHECKSUM: 0e23ef3e43ff7a2a471fd59d57def6d19f6f9e9e

Expand Down
3 changes: 1 addition & 2 deletions Mintfile
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
realm/SwiftLint@0.43.1

realm/SwiftLint@0.44.0
1 change: 0 additions & 1 deletion Sources/TiltUp/Screens/Camera/CameraController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ public final class CameraController: UIViewController {

overlayView.frame = view.bounds
previewView.frame = overlayView.previewImageView.frame

}
}

Expand Down
98 changes: 63 additions & 35 deletions Sources/TiltUp/Screens/Camera/CameraViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,31 @@ public final class CameraViewModel: NSObject {

super.init()

fetchSetupResult()

sessionQueue.async(execute: configureSession)

updateVideoOrientationForDeviceOrientation()
NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil)

NotificationCenter.default.addObserver(self, selector: #selector(wasInterrupted), name: .AVCaptureSessionWasInterrupted, object: session)

NotificationCenter.default.addObserver(self, selector: #selector(subjectAreaChanged), name: .AVCaptureDeviceSubjectAreaDidChange, object: nil)
}

func viewWillAppear() {
sessionQueue.async(execute: startSession)
viewObservers.rotateInterface?(currentVideoOrientation)
}

func viewWillDisappear() {
sessionQueue.async(execute: stopSession)
}

private func fetchSetupResult() {
#if targetEnvironment(simulator)
setupResult = .pending
#else
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
break
Expand All @@ -121,30 +146,14 @@ public final class CameraViewModel: NSObject {
@unknown default:
setupResult = .notAuthorized
}

sessionQueue.async(execute: configureSession)

updateVideoOrientationForDeviceOrientation()
NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil)

NotificationCenter.default.addObserver(self, selector: #selector(wasInterrupted), name: .AVCaptureSessionWasInterrupted, object: session)

NotificationCenter.default.addObserver(self, selector: #selector(subjectAreaChanged), name: .AVCaptureDeviceSubjectAreaDidChange, object: nil)
}

func viewWillAppear() {
sessionQueue.async(execute: startSession)
viewObservers.rotateInterface?(currentVideoOrientation)
}

func viewWillDisappear() {
sessionQueue.async(execute: stopSession)
#endif
}
}

// MARK: Session
private extension CameraViewModel {
func configureSession() {
#if !targetEnvironment(simulator)
guard setupResult == .pending else { return }

session.beginConfiguration()
Expand Down Expand Up @@ -207,6 +216,7 @@ private extension CameraViewModel {
resetFocus()

viewObservers.updatePreviewSession?(session)
#endif
}

func startSession() {
Expand Down Expand Up @@ -266,7 +276,13 @@ private extension CameraViewModel {

// MARK: Capture
private extension CameraViewModel {
func capturePhoto() {
func captureMockPhoto() {
guard let photoCapture = PhotoCapture.mock() else { return }
photoCapturePrepared(photoCapture)
viewObservers.didCapturePhotoAnimation?()
}

func captureLivePhoto() {
if let photoOutputConnection = photoOutput.connection(with: .video) {
photoOutputConnection.videoOrientation = currentVideoOrientation
}
Expand Down Expand Up @@ -295,26 +311,19 @@ private extension CameraViewModel {
photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureDelegate)
}

func capturePhoto() {
#if targetEnvironment(simulator)
captureMockPhoto()
#else
captureLivePhoto()
#endif
}

func capturePhotoCompletion(_ photoCaptureDelegate: PhotoCaptureDelegate) {
resetFocus()

if let photoCapture = photoCaptureDelegate.photoCapture {
var remainingPhotoType: CameraOverlayView.RemainingPhotoType = .none
let photoCountIncludingCurrentPhoto = photos.count + 1
if photoCountIncludingCurrentPhoto < settings.numberOfPhotos.upperBound {
if photoCountIncludingCurrentPhoto >= settings.numberOfPhotos.lowerBound {
remainingPhotoType = .optional
} else {
remainingPhotoType = .required
}
}

viewObservers.updateOverlayState?(
.confirm(
photoCapture: photoCapture,
remainingPhotoType: remainingPhotoType
)
)
photoCapturePrepared(photoCapture)
}

// When the capture is complete, remove a reference to the photo capture delegate so it can be deallocated.
Expand All @@ -324,6 +333,25 @@ private extension CameraViewModel {

viewObservers.didCapturePhotoAnimation?()
}

func photoCapturePrepared(_ photoCapture: PhotoCapture) {
var remainingPhotoType: CameraOverlayView.RemainingPhotoType = .none
let photoCountIncludingCurrentPhoto = photos.count + 1
if photoCountIncludingCurrentPhoto < settings.numberOfPhotos.upperBound {
if photoCountIncludingCurrentPhoto >= settings.numberOfPhotos.lowerBound {
remainingPhotoType = .optional
} else {
remainingPhotoType = .required
}
}

viewObservers.updateOverlayState?(
.confirm(
photoCapture: photoCapture,
remainingPhotoType: remainingPhotoType
)
)
}
}

// MARK: - Camera
Expand Down
10 changes: 10 additions & 0 deletions Sources/TiltUp/Screens/Camera/PhotoCapture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ public struct PhotoCapture {
public let expectedCaptureDuration: Measurement<UnitDuration>
public let actualCaptureDuration: Measurement<UnitDuration>

static func mock() -> PhotoCapture? {
let image = UIImage.make(color: UIColor.cyan, size: CGSize(width: 640, height: 640))

return PhotoCapture(
forStubbingWith: image,
expectedCaptureDuration: .init(value: 0, unit: .seconds),
actualCaptureDuration: .init(value: 0, unit: .seconds)
)
}

init?(
capture: AVCapturePhoto,
expectedCaptureDuration: Measurement<UnitDuration>,
Expand Down
2 changes: 1 addition & 1 deletion TiltUp.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TiltUp'
s.version = '3.0.1'
s.version = '3.1.0'
s.summary = 'Official Clutter SDK in Swift to access core iOS features.'

s.description = <<-DESC
Expand Down
2 changes: 1 addition & 1 deletion TiltUpTest.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TiltUpTest'
s.version = '3.0.1'
s.version = '3.1.0'
s.summary = 'Official Clutter SDK in Swift to access core iOS test helpers.'

s.description = <<-DESC
Expand Down

0 comments on commit 6a865b8

Please sign in to comment.