SwiftUI Live Camera Feed App with Rotation Support

Building a live camera feed app in SwiftUI is exciting, but handling screen rotations adds complexity. This tutorial guides you through creating a robust SwiftUI app that seamlessly integrates a live camera feed and dynamically adapts to device rotations. We'll cover essential techniques, ensuring your app remains responsive and user-friendly regardless of orientation. Let's dive in and build a polished, rotation-aware camera app!

Step-by-Step Instructions

  1. Set up the Project Structure

    • Host a `UIViewController` in a SwiftUI view. Replace `HelloWorld` in `ContentView` with `HostedViewController`.
    • Create a new Swift file for the `UIViewController` (named `HostedViewController`). Import UIKit, AVFoundation, and Foundation.
    • Create a `UIViewController` subclass (`ViewController`) to handle camera access and feed presentation.
    • Create a `UIViewControllerRepresentable` to wrap the `UIViewController` in a SwiftUI view.
    Create a `UIViewControllerRepresentable` to wrap the `UIViewController` in a SwiftUI view. Create a `UIViewControllerRepresentable` to wrap the `UIViewController` in a SwiftUI view. Create a `UIViewControllerRepresentable` to wrap the `UIViewController` in a SwiftUI view. Create a `UIViewControllerRepresentable` to wrap the `UIViewController` in a SwiftUI view.
    Set up the Project Structure
  2. Request and Handle Camera Permissions

    • Check camera permission. If granted, set up the capture session.
    • Add a privacy `NSUserDescription` (in your project's Info.plist) to request camera permission.
    • Implement `checkPermission()` to handle permission requests asynchronously, suspending the session queue until permission is granted.
    Implement `checkPermission()` to handle permission requests asynchronously, suspending the session queue until permission is granted. Implement `checkPermission()` to handle permission requests asynchronously, suspending the session queue until permission is granted. Implement `checkPermission()` to handle permission requests asynchronously, suspending the session queue until permission is granted.
    Request and Handle Camera Permissions
  3. Configure the Camera Capture Session

    • add input (camera), output (preview layer), and handle rotation.
    Implement `setupCaptureSession()` to configure the capture session: add input (camera), output (preview layer), and handle rotation.
    Configure the Camera Capture Session
  4. Set up the Camera Preview Layer

    • Create and configure the `AVCaptureVideoPreviewLayer` to display the camera feed. Set its size and position based on screen orientation.
    • Add the preview layer to the root view's layer on the main queue.
    Add the preview layer to the root view's layer on the main queue. Add the preview layer to the root view's layer on the main queue.
    Set up the Camera Preview Layer
  5. Implement Rotation Support

    • Override `viewWillTransition(to:with:)` to detect orientation changes. Update `screenRect` and `previewLayer`'s frame and connection's video orientation.
    Override `viewWillTransition(to:with:)` to detect orientation changes. Update `screenRect` and `previewLayer`'s frame and connection's video orientation.
    Implement Rotation Support
[RelatedPost]

Tips

  • Use asynchronous operations (like permission requests) and dispatch queues (`sessionQueue`, `mainQueue`) to ensure smooth UI updates and prevent blocking.
  • Handle landscape left/right orientations correctly, accounting for the difference between device and layer orientation.

Common Mistakes to Avoid

1. Incorrect Camera Access Permissions

Reason: The app requests camera access incorrectly or doesn't handle permission denials gracefully, resulting in a blank screen or a crash.
Solution: Ensure you have the correct `NSCameraUsageDescription` key in your `Info.plist` and handle permission requests and denials appropriately within your code.

2. Ignoring Device Orientation Changes

Reason: The app doesn't adapt the preview layer to the device's rotation, resulting in a distorted or incorrectly oriented camera feed.
Solution: Use the `UIViewControllerRepresentable`'s `updateUIViewController` method to adjust the preview layer's transform based on the device's current orientation.

3. Memory Leaks and Performance Issues

Reason: Inefficient handling of the camera feed and preview layer can lead to memory leaks and sluggish performance, particularly on older devices.
Solution: Use `@State` objects effectively, release captured images when no longer needed, and consider using lower resolutions when appropriate.

FAQs

My camera feed is distorted or shows incorrect proportions after rotation. What could be causing this?
This often happens due to incorrect aspect ratio handling. Ensure you're using a `GeometryReader` to adapt the preview layer's frame to the available screen space after rotation. Also, check that your camera's output resolution and the view's aspect ratio are compatible. Consider using `AVCaptureVideoPreviewLayer`'s `videoGravity` property to control scaling behavior (e.g., `AVLayerVideoGravityResizeAspectFill`).
How do I handle permissions for camera access within my SwiftUI app?
You need to request camera access permission using `AVCaptureDevice.requestAccess(for:)`. This should be done early in your app's lifecycle, ideally when the camera feature is first accessed. Handle the result of the request gracefully, informing the user if permission is denied and providing options to adjust their settings if needed. Remember to add the `NSCameraUsageDescription` key to your `Info.plist` with a clear explanation of why your app needs camera access.