Skip to content

kasimok/lockCameraExtensionDemo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

the CameraCaptureIntent protocol allows you to define an associated AppContext type (up to 4KB) that gets passed to your LockedCameraCaptureExtension when the intent is triggered from the Lock Screen control.

Below is the steps to pass data with this AppContext

  1. Define Your AppContext

Create a Codable struct that conforms to the requirements for use as an AppContext. The key is making all methods nonisolated so the type is usable as Sendable:

import AppIntents

/// The appContext contains user preferences for the camera capture
struct MyAppContext: Codable {
    /// Control which camera to use: true for front camera, false for rear camera
    var useFrontCamera: Bool

    enum CodingKeys: String, CodingKey {
        case useFrontCamera
    }

    // Make initializers and Codable methods nonisolated so the type is usable as a Sendable AppContext.
    nonisolated init(useFrontCamera: Bool) {
        self.useFrontCamera = useFrontCamera
    }

    nonisolated init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.useFrontCamera = try container.decode(Bool.self, forKey: .useFrontCamera)
    }

    nonisolated func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(useFrontCamera, forKey: .useFrontCamera)
    }
}
  1. Create Your CameraCaptureIntent Define your intent and associate it with your AppContext:
struct MyCamCaptureIntent: CameraCaptureIntent {
    
    typealias AppContext = MyAppContext
    
    static let title: LocalizedStringResource = "Camera"
    static let description = IntentDescription("Capture photos with your app.")
    
    func perform() async throws -> some IntentResult {
        // Return empty result - the context is automatically passed to the extension
        return .result()
    }
}

Important!!!! Make sure this file is included in all three targets:

  • Main app
  • Widget extension
  • Capture extension
  1. Update Context from Your Main App In your main app's view controller, update the context when user preferences change:
import AppIntents

class ViewController: UIViewController {
    
    private let frontBackSwitch: UISwitch = UISwitch()
    
    @objc private func frontBackPreferenceChanged() {
        updateIntentContext()
    }
    
    private func setupUI() {
        frontBackSwitch.addTarget(self, action: #selector(frontBackPreferenceChanged), for: .valueChanged)
   }

    
    private func updateIntentContext() {
        Task {
            let newContext = MyAppContext(useFrontCamera: cameraSwitch.isOn)
            try? await MyCamCaptureIntent.updateAppContext(newContext)
        }
    }
    
    private func loadSettings() {
        Task { @MainActor in
            let context = try? await MyCamCaptureIntent.appContext
            frontBackSwitch.isOn = context?.useFrontCamera ?? false
        }
    }
}

Step 4: Read Context in Your Capture Extension In your capture extension's UI, access the context to configure the camera:

import SwiftUI
import UIKit
import UniformTypeIdentifiers
import LockedCameraCapture
import AppIntents

struct Viewfinder: UIViewControllerRepresentable {
    let session: LockedCameraCaptureSession
    
    func makeUIViewController(context: Context) -> UIImagePickerController {
        let imagePicker = UIImagePickerController()
        imagePicker.sourceType = .camera
        
        // Read the AppContext to configure camera
        Task { @MainActor in
            if let appContext = try? await MyCamCaptureIntent.appContext {
                imagePicker.cameraDevice = appContext.useFrontCamera ? .front : .rear
                print("Camera device set to: \(appContext.useFrontCamera ? "front" : "rear")")
            } else {
                imagePicker.cameraDevice = .rear
            }
        }
        
        return imagePicker
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
}

This approach provides a clean, type-safe way to pass user preferences from your main app to your Lock Screen camera capture extension!

About

Demonstrate how to pass data between a main app and a lockscreencaptureextension

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages