You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+97-23Lines changed: 97 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,32 +1,38 @@
1
1
# ScreenShieldKit
2
2
3
-
A Swift package to protect sensitive content from screenshots and screen recording on iOS and macOS platforms.
3
+
A Swift package that protects sensitive content from screenshots and screen recordings across Apple platforms — for UIKit, AppKit, Core Animation, and **SwiftUI**.
4
4
5
5
## Overview
6
6
7
-
ScreenShieldKit provides an easy-to-use API to prevent content from being captured in screenshots or screen recordings. This is especially useful for applications that display sensitive information such as:
7
+
ScreenShieldKit hides selected content from screenshots, screen recordings, and other system captures while it stays fully visible on the device. This is useful for screens that display sensitive information such as:
8
8
9
-
- Financial data
9
+
- Financial data (balances, card numbers)
10
10
- Personal identification information
11
+
- One-time passcodes and authentication screens
11
12
- Confidential documents
12
-
- Authentication screens
13
+
14
+
The protection is scoped: you protect only the views that contain secrets, and the rest of your UI is captured normally.
Add ScreenShieldKit to your project through Xcode's Package Dependencies:
29
+
Add ScreenShieldKit through Xcode's **File → Add Packages…** with the URL:
24
30
25
-
1. In Xcode, select "File" → "Add Packages..."
26
-
2. Enter the repository URL: `https://github.com/daangn/ScreenShieldKit.git`
27
-
3. Choose the version you want to use
31
+
```
32
+
https://github.com/daangn/ScreenShieldKit.git
33
+
```
28
34
29
-
Or add it to your `Package.swift` file:
35
+
Or add it to your `Package.swift`:
30
36
31
37
```swift
32
38
dependencies: [
@@ -36,31 +42,99 @@ dependencies: [
36
42
37
43
## Usage
38
44
39
-
### Basic Usage
45
+
### SwiftUI
46
+
47
+
Apply the `.screenShield(_:)` modifier to any view you want to hide from captures:
48
+
49
+
```swift
50
+
importScreenShieldKit
51
+
importSwiftUI
52
+
53
+
Text(oneTimeCode)
54
+
.font(.system(.title, design: .monospaced))
55
+
.screenShield()
56
+
```
57
+
58
+
To protect several views at once, group them and apply the modifier a single time:
59
+
60
+
```swift
61
+
VStack {
62
+
AccountBalanceView()
63
+
CardNumberView()
64
+
}
65
+
.screenShield()
66
+
```
67
+
68
+
**Dynamic on/off**
69
+
70
+
Pass a `Bool` that participates in SwiftUI state to toggle protection at runtime:
71
+
72
+
```swift
73
+
structCardView: View {
74
+
@Stateprivatevar isSensitive =true
75
+
76
+
var body: some View {
77
+
VStack {
78
+
Toggle("Protect content", isOn: $isSensitive)
79
+
80
+
Text("1234 5678 9012 3456")
81
+
.screenShield(isSensitive)
82
+
}
83
+
}
84
+
}
85
+
```
86
+
87
+
Toggling protection preserves the wrapped content's identity: it never inserts or removes views based on the flag, so the content's `@State`, scroll position, focus, and in-flight animations are **not** reset when you switch protection on or off.
ScreenShieldKit selects a mechanism per platform and OS version:
119
+
120
+
| Path | OS | Mechanism |
121
+
| --- | --- | --- |
122
+
| SwiftUI (native) | iOS 18 / macOS 15 / tvOS 18 / watchOS 11 / visionOS 2+ | Activates SwiftUI's native capture-redaction reason in the environment. Fully transparent to layout; no hosting boundary. |
123
+
| SwiftUI (legacy) | iOS 16–17 / macOS 13–14 / tvOS 16–17 / visionOS 1 | Hosts the content in a hosting controller and applies the Core Animation capture flag to its backing layer. |
124
+
| UIKit / AppKit / CALayer | iOS 14+ / macOS 11+ | Applies the Core Animation capture flag directly to the layer. |
125
+
126
+
The SwiftUI native path is preferred where available because it composes cleanly with SwiftUI layout and state. The legacy path re-hosts the content, but SwiftUI keeps propagating the ancestor environment across the hosting boundary, so `@Environment` values and `@EnvironmentObject` dependencies still reach the shielded content.
127
+
128
+
## Important notes
129
+
130
+
-**Private platform behavior.** ScreenShieldKit relies on private platform behavior that can change between OS releases. When the mechanism is unavailable on a device, the call becomes a safe no-op (it never crashes). **Verify capture protection on every OS version you support** — with screenshots, screen recordings, AirPlay mirroring, and any in-app capture flow that matters for your product.
131
+
-**App Store.** The library avoids private selectors and private symbol references: the SwiftUI native path constructs the capture-redaction option value directly, and the Core Animation path resolves its property key at runtime. Even so, using private platform behavior carries review risk you should evaluate for your app.
132
+
-**`privacySensitive` interaction (SwiftUI native path).** On the native path (iOS 18 / macOS 15 / tvOS 18 / watchOS 11 / visionOS 2+), the shielded subtree is forced non-privacy-sensitive — even when `isProtected` is `false` — so activating the capture-redaction reason never blanks the content on device. Avoid relying on `.privacySensitive()` inside a `.screenShield()` boundary. The legacy path does not apply this, since it hides via the layer flag rather than a redaction reason.
133
+
-**macOS is best-effort.** On macOS, layer-level capture hiding may not hide content from every system capture path.
134
+
135
+
## Sample
60
136
61
-
- This library uses private APIs which may not be approved for App Store submission
62
-
- The protection mechanism may change in future OS versions
63
-
- For macOS, the view must have a backing layer for the protection to work
137
+
The `Sample/` app has two tabs — a UIKit demo and a SwiftUI demo — both driving protection from a toggle. The sample targets iOS 16 so you can exercise the legacy and native SwiftUI paths on the OS versions you support.
"Take a screenshot or start a screen recording. The shielded content is hidden from the capture but stays visible here. Toggling protection keeps the views' state intact."
0 commit comments