BSSecureKit is a secure view component library for iOS applications that protects sensitive content from screenshots and screen recordings. It provides components for both UIKit and SwiftUI frameworks.
| Screenshot Result | Actual Screen |
|---|---|
![]() |
![]() |
- Secure Overlay: Protects sensitive content from screenshots and screen recordings
- Dynamic Security Control: Toggle security state on/off at runtime using
isSecureproperty - AutoFill Bar Prevention: Keeps the password AutoFill bar from appearing for other text inputs on the same screen, controlled by the
preventsAutoFillinitializer parameter - iOS 13.0+ Support: Compatible with the latest iOS versions (tested up to iOS 26.0)
- UIKit & SwiftUI Support: Works with both frameworks
- Simple Usage: Minimal code required to implement security features
dependencies: [
.package(url: "https://github.com/Bangs00/BSSecureKit.git", from: "1.2.0")
]pod 'BSSecureKit', '~> 1.2.0'You can clone the repository or download the ZIP file and add it directly to your project.
import BSSecureKit
// Basic usage
let secureView = BSSecureView()
let contentLabel = UILabel()
contentLabel.text = "Sensitive Information"
secureView.embed(contentLabel)
// Dynamic security control
secureView.isSecure = true // Enable security
secureView.isSecure = false // Disable security
// Alternative method using function
secureView.setSecure(true) // Enable security
secureView.setSecure(false) // Disable security
// AutoFill bar prevention (enabled by default, fixed at initialization)
let plainSecureView = BSSecureView(preventsAutoFill: false)
let framedSecureView = BSSecureView(frame: .zero, preventsAutoFill: false)
// With placeholder
let placeholderView = UIView()
let placeholderLabel = UILabel()
placeholderLabel.text = "Placeholder"
let overlaySecureView = BSSecureView()
let secureLabel = UILabel()
secureLabel.text = "Actual Sensitive Information"
overlaySecureView.embed(secureLabel)
placeholderView.addSubview(placeholderLabel)
placeholderView.addSubview(overlaySecureView)import SwiftUI
import BSSecureKit
struct SecureContentView: View {
@State private var isSecured = true
var body: some View {
VStack {
// Regular content
Text("Regular Content")
.padding()
.background(Color.orange)
// Basic secure content (always secured)
BSSecureViewRepresentable {
Text("Sensitive Information")
.padding()
.background(Color.green)
}
// Secure content with dynamic control
BSSecureViewRepresentable(isSecure: isSecured) {
Text("Sensitive Information")
.padding()
.background(Color.green)
}
// Secure content with AutoFill bar prevention turned off
BSSecureViewRepresentable(isSecure: isSecured, preventsAutoFill: false) {
Text("Sensitive Information")
.padding()
.background(Color.green)
}
// Placeholder with secure content
ZStack {
Text("Placeholder")
.padding()
.background(Color.red)
BSSecureViewRepresentable(isSecure: isSecured) {
Text("Actual Sensitive Information")
.padding()
.background(Color.blue)
}
}
// Toggle button to control security state
Button(action: {
isSecured.toggle()
}) {
Text(isSecured ? "Secured" : "Not Secured")
.frame(maxWidth: .infinity)
.frame(height: 44)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
}
.padding()
}
}The secure overlay is built on a UITextField with isSecureTextEntry enabled. While that field
stays in the view hierarchy, UIKit's AutoFill heuristic treats the screen as a password form and
shows the password AutoFill bar above the keyboard when the user focuses any other text input
on the same screen.
Capture protection is applied on the layer, not on the view. So when preventsAutoFill is true,
BSSecureView detaches the secure field from the view hierarchy on the first layout pass that runs
after the overlay is set up and the view has a real size, and keeps its layer in the render tree.
The AutoFill bar no longer appears and the content stays protected.
let secureView = BSSecureView() // preventsAutoFill: true
let plainView = BSSecureView(preventsAutoFill: false) // Opt outFixed at initialization: UIKit decides whether to show the AutoFill bar when a text input begins
editing, so the secure field has to be out of the view hierarchy before that happens. The option is
therefore set at initialization only — preventsAutoFill is read-only afterwards, and changing the
value passed to BSSecureViewRepresentable after the view is created has no effect.
Trade-off: the detached field no longer participates in Auto Layout, so its frame is updated in
layoutSubviews, which is called often. The update is skipped when the bounds are unchanged, but if
your screen has no other text input — or the AutoFill bar is not a problem for you — pass
preventsAutoFill: false to skip the work entirely.
This repository includes two example projects:
- Example-UIKit: UIKit implementation example
- Example-SwiftUI: SwiftUI implementation example
Each example demonstrates:
- Comparison between regular and secure content
- Basic secure view usage
- Combination of placeholder and secure content
- Dynamic security state control with toggle functionality
- iOS 13.0+ (tested up to iOS 26.0)
- Swift 5.3+
- Xcode 12.0+
- iOS Physical Device (does not work on Mac)
This library has been tested on:
- iOS 13.0 through iOS 26.0
- Both UIKit and SwiftUI implementations
Note: The security features only work on physical iOS devices. When testing on Mac, the secure overlay will not function as expected.
This project is licensed under the MIT License. See the LICENSE file for details.
Bug reports, feature requests, and pull requests are welcome!


