Skip to content

sentryco/LockScreenView

Repository files navigation

Tests codebeat badge License MIT Platforms Swift Package Manager Swift Version

LockScreenView

Add lockability to your app

Features

  • Add your own "lock-UI"
  • Add your own "authentication-handler"
  • Avoids locking the app if there are active alerts or sheets (iOS only, because alerts and sheets are above the app views, and as such cant be locked, unless dismissed, which can result in data loss)
  • Designed entirely with SwiftUI, ensuring smooth integration with modern iOS and macOS applications.
  • Automatically manages app locking and unlocking based on the app's lifecycle events
  • Has translucent overlay bellow lockview as standard

Example

  • This example demonstrates how to integrate the LockScreenView into your SwiftUI application. It shows a basic setup where the lock screen is presented based on the app's authentication state.
  • This example provides a clear and concise demonstration of how to use the LockScreenView in a SwiftUI application, including a basic lock screen setup. Adjust the example as necessary to fit the specific functionalities and design of your application.
import SwiftUI
import LockScreenView

struct ContentView: View {
    @State private var isLocked = true

    var body: some View {
        LockView(
            content: { MainView() },
            lockScreen: { LockScreen(isLocked: $isLocked) },
            isLocked: $isLocked
        )
    }
}

struct MainView: View {
    var body: some View {
        Text("Main App Content")
            .font(.largeTitle)
            .padding()
    }
}

struct LockScreen: View {
    @Binding var isLocked: Bool
    @State private var password: String = ""

    var body: some View {
        VStack(spacing: 20) {
            Text("Enter your password")
                .font(.headline)
            SecureField("Password", text: $password)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding(.horizontal)
            Button("Unlock") {
                if password == "abc123" {
                    isLocked = false
                }
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(10)
        }
        .padding()
        .background(Color(.systemBackground))
        .cornerRadius(15)
        .shadow(radius: 10)
    }
}

Aditional example:

Add a container wrapper to contain the state and add more functionality like

struct LockViewModifier: ViewModifier {
    @State private var isLocked: Bool = true

    func body(content: Content) -> some View {
        LockView(
            content: { content },
            lockScreen: { lockScreen },
            isLocked: $isLocked,
            onScenePhaseChange: handlePhaseChange
        )
    }

    var lockScreen: some View {
        // Implement your custom lock screen UI here
        EmptyView()
    }

    fileprivate func handlePhaseChange(oldPhase: ScenePhase, newPhase: ScenePhase) {
        switch newPhase {
        case .background, .inactive:
            #if os(iOS)
            if isModalPresented { return } // Skip locking app if alert or sheet is active
            #endif
            if oldPhase == .active {
                isLocked = true
            }
        case .active:
            if oldPhase != .active {
                isLocked = true // Lock app when returning from background
            } else {
                print("This should not happen")
            }
        @unknown default:
            print("Unknown newPhase")
        }
    }
}

extension View {
    /**
     Wraps the `LockViewModifier` around the calling view.

     Usage:
     ```swift
     Text("Hello, World!").lockView()
     ```
     */
    func lockView() -> some View {
        self.modifier(LockViewModifier())
    }
}

Installation

Swift Package Manager:

.package(url: "https://github.com/sentryco/LockScreenView", branch: "main")

Dependencies

Note

macOS Limitations On macOS, detecting active alerts and sheets to prevent the app from locking is more complex due to differences in how modals are handled compared to iOS. Currently, LockScreenView avoids locking the app if there are active alerts or sheets on iOS only. We are researching methods to achieve similar functionality on macOS, possibly by exploring environment variables like presentationMode.isPresented.

Todo:

  • Improve the readme
  • Add the improved example code
  • Add info regarding why it's hard to detect alerts and sheets for macOS
  • There might be a way to detect alerts and sheets for macOS, more thinking / exploration / research needed
  • Look into the environment variable presentationMode.isPresented etc, it might be key to asserting if alert/sheet is presented for macOS, from a global
  • Create a Demo App: Develop a sample application that showcases LockScreenView in action, demonstrating features like custom lock screens and authentication handlers.
  • Research AppKit APIs: Investigate AppKit methods for detecting modals on macOS, such as using NSApplication notifications or key window checks.

Releases

No releases published

Packages

No packages published

Languages