Point-and-shoot camera for iOS apps
A single-lens, single-use alternative to UIImagePickerController
, Snap
covers the most common in-app picture-taking use case. Zero configuration, unless you want to pick a different lens or enable the flash. Takes one auto-focused JPEG at a time.
Written in Swift 5.10 for iOS 17. Build with Xcode 15 or newer.
Present Snap.Camera
using one of two included view modifiers for sheet and full-screen-cover modal presentations:
import SwiftUI
import Snap
struct ContentView: View {
@State var isPresented: Bool = false
@State var isCapturing: Bool = false
@State var image: Camera.Image?
var body: some View {
VStack {
Image(image)
.resizable()
.aspectRatio(contentMode: .fit)
Button(action: { isPresented.toggle() }) {
Label("Camera", systemImage: "camera")
}
.sheet($isPresented) {
Camera($isCapturing) { image in
self.image = image
isPresented.toggle()
}
}
}
}
}
Toggle $isCapturing
true to trigger the shutter programmatically. Captured still images are delivered as Data
with UTType public.jpeg
.
Snap.Camera
automatically selects the 1x-iest built-in rear camera available. Easily flip that to front-facing camera or pick your own:
Camera.device = .default() // .default(.back)
Camera.device = .default(.front)
Camera.device = Camera.Device([
.builtInDualCamera,
.builtInWideAngleCamera // Select first available
], position: .back)
Camera.quality = .balanced // Default
Camera.quality = .speed
Camera.quality = .quality
Camera.flash = .off // Default
Camera.flash = .auto
Camera
holds the core functionality:
- Interface binding to trigger the camera shutter
- Handler to deliver a JPEG image of the configured quality, using the configured camera
- Live video preview that scales to fill its SwiftUI containing view
- Video preview flashes to indicate shutter release
Use Camera.shutterToggle(_ alignment: Alignment)
modifier to add a shutter button:
@State var isCapturing: Bool = false
@State var error: Error? = nil
Camera($isCapturing, error: $error) { image in
// image.fileType: public.jpeg
// image.data: 2901515 bytes
}
.shutterToggle() // Default alignment: .bottom
The Snap.Camera
sheet/full-screen presentations use a handy ViewModifier
to keep the screen awake:
import Snap
EmptyView()
.disableIdleTimer() // .disableIdleTimer(300.0)
.disableIdleTimer(86400.0) // Lowest value wins
SwiftUI is gonna get a first-party camera Picker
of some kind eventually. In the meantime, ImagePicker
wraps UIImagePickerController
for when you need features that Snap.Camera
doesn't cover:
- User-adjustable zoom and flash
- Review, edit and retake
- Hardware volume button shutter release
- Movie recording
Present ImagePicker
with the included view modifier, then handle any captured media:
import Snap
@State private var isPresented: Bool = false
Button(action: { isPresented.toggle() }) {
Label("Camera", systemImage: "camera")
}
.imagePicker($isPresented, media: [.image, .movie]) { info in
// info: [UIImagePickerController.InfoKey: Any]
}
UIImagePickerController
is designed to be locked in portrait orientation only, but UIViewControllerRepresentable
ignores view controller orientation locking. Hilarity ensues unless your app is portrait only. Otherwise, stick to presenting from UIKit for now.
ImagePicker
or UIImagePickerController
requires an additional target info privacy description for microphone usage.