Protect sensitive UIKit content from screenshots and screen recordings.
ScreenshotShield is a lightweight Swift package that helps you protect sensitive content in your iOS app from being captured in screenshots or screen recordings. Perfect for banking apps, password managers, confidential documents, and any app handling sensitive data.
- Prevent sensitive content from appearing in screenshots
- Detect and respond to screen recording/mirroring
- Easy-to-use UIKit components
- Customizable blocked overlay
- Supports iOS 13+
- Zero dependencies
Add ScreenshotShield to your project using Xcode:
- Go to File → Add Package Dependencies...
- Enter the repository URL:
https://github.com/abdorizak/ScreenshotShield.git - Select your version rules and add to your target
Or add it to your Package.swift:
dependencies: [
.package(url: "https://github.com/abdorizak/ScreenshotShield.git", from: "1.0.0")
]import ScreenshotShield
class ConfidentialViewController: UIViewController {
private let secureContainer = SecureContainerView()
private let blockedOverlay = ScreenshotBlockedOverlay()
override func viewDidLoad() {
super.viewDidLoad()
// 1. Add overlay FIRST (it will be behind)
view.addSubview(blockedOverlay)
// 2. Add secure container ON TOP
view.addSubview(secureContainer)
// 3. Layout both views
blockedOverlay.translatesAutoresizingMaskIntoConstraints = false
secureContainer.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
blockedOverlay.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
blockedOverlay.leadingAnchor.constraint(equalTo: view.leadingAnchor),
blockedOverlay.trailingAnchor.constraint(equalTo: view.trailingAnchor),
blockedOverlay.bottomAnchor.constraint(equalTo: view.bottomAnchor),
secureContainer.topAnchor.constraint(equalTo: view.topAnchor),
secureContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
secureContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor),
secureContainer.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
// 4. Add your sensitive content to the secure container
setupSecureContent()
}
private func setupSecureContent() {
let content = secureContainer.contentView
content.backgroundColor = .systemBackground
let secretLabel = UILabel()
secretLabel.text = "API Key: sk_live_abc123xyz"
secretLabel.font = .monospacedSystemFont(ofSize: 16, weight: .regular)
content.addSubview(secretLabel)
secretLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
secretLabel.centerXAnchor.constraint(equalTo: content.centerXAnchor),
secretLabel.centerYAnchor.constraint(equalTo: content.centerYAnchor),
])
}
}ScreenshotShield leverages iOS's secure text field mechanism:
- Normal App Usage: Your content is fully visible and interactive
- Screenshot Taken: iOS automatically blanks the secure content, revealing the overlay behind
- Screen Recording: The library detects recording and can notify you to take action
┌─────────────────────────────────┐
│ ScreenshotBlockedOverlay │ ← Behind (visible in screenshots)
├─────────────────────────────────┤
│ SecureContainerView │ ← On top (blanked in screenshots)
│ ┌─────────────────────────┐ │
│ │ contentView │ │
│ │ (your sensitive UI) │ │
│ └─────────────────────────┘ │
└─────────────────────────────────┘
The main container that protects its content from screenshots.
let secureContainer = SecureContainerView()
// Add content to the contentView
secureContainer.contentView.addSubview(mySecretView)
// Toggle protection on/off
secureContainer.isProtectionEnabled = true
// Listen for screen capture changes
secureContainer.onScreenCaptureStateChanged = { isCaptured in
if isCaptured {
print("Screen is being recorded!")
}
}
// Check current capture state
if secureContainer.isScreenBeingCaptured {
// Handle screen recording
}A pre-built overlay to display when content is blocked.
// Default styling
let overlay = ScreenshotBlockedOverlay()
// Custom styling
let customOverlay = ScreenshotBlockedOverlay(
icon: UIImage(systemName: "lock.shield.fill"),
title: "Protected Content",
message: "Screenshots are not allowed for security reasons.",
backgroundColor: .systemBackground
)
// Modify after creation
overlay.icon = UIImage(systemName: "exclamationmark.triangle.fill")
overlay.iconTintColor = .systemOrange
overlay.title = "Access Restricted"
overlay.message = "Please disable screen recording to continue."
overlay.iconSize = 80Static utilities for screen capture detection.
// Check if screen is being captured
if ScreenshotShield.isScreenBeingCaptured {
// Handle accordingly
}
// Observe screen capture changes globally
let observer = ScreenshotShield.observeScreenCapture { isCaptured in
print("Screen capture state: \(isCaptured)")
}
// Remove observer when done
ScreenshotShield.removeObserver(observer)class SettingsViewController: UIViewController {
private let secureContainer = SecureContainerView()
private let blockedOverlay = ScreenshotBlockedOverlay()
private let protectionSwitch = UISwitch()
override func viewDidLoad() {
super.viewDidLoad()
// Setup views...
protectionSwitch.isOn = true
protectionSwitch.addTarget(self, action: #selector(toggleProtection), for: .valueChanged)
}
@objc private func toggleProtection() {
secureContainer.isProtectionEnabled = protectionSwitch.isOn
blockedOverlay.isHidden = !protectionSwitch.isOn
}
}class BankingViewController: UIViewController {
private let secureContainer = SecureContainerView()
private let blockedOverlay = ScreenshotBlockedOverlay()
override func viewDidLoad() {
super.viewDidLoad()
// Setup views...
// Handle screen recording
secureContainer.onScreenCaptureStateChanged = { [weak self] isCaptured in
self?.handleScreenCapture(isCaptured)
}
}
private func handleScreenCapture(_ isCaptured: Bool) {
if isCaptured {
// Bring overlay to front during recording
view.bringSubviewToFront(blockedOverlay)
blockedOverlay.isHidden = false
} else {
// Send overlay back behind container
view.sendSubviewToBack(blockedOverlay)
}
}
}- iOS 13.0+
- Swift 5.9+
- Xcode 15.0+
- This protection relies on iOS's internal secure text field behavior
- The behavior may vary slightly across different iOS versions
- Screen recording detection notifies after recording starts (cannot prevent)
- Not a guarantee against all forms of capture (e.g., external cameras)
Contributions are welcome! Please feel free to submit a Pull Request.
ScreenshotShield is available under the MIT license. See the LICENSE file for more info.
Abdul Razak — abdorizak.dev
Made with love for the UIKit community.