I searched for many solutions and tried so many things a few years ago. Nothing is as simple and amazing as this solution. You can add ".captureProtected()" to anything you want. Image, text. An entire view. It all works. Clean and simple. No plug in no weird code and bad workarounds.
import SwiftUI
import UIKit
private extension UIView {
// Secure container borrowed from UITextField
static var secureCaptureView: UIView {
let tf = UITextField()
tf.isSecureTextEntry = true
tf.isUserInteractionEnabled = false
return tf.subviews.first ?? UIView()
}
}
private struct _CaptureProtectedContainer<Content: View>: UIViewRepresentable {
let content: Content
func makeUIView(context: Context) -> UIView {
let secure = UIView.secureCaptureView
let host = UIHostingController(rootView: content)
host.view.backgroundColor = .clear
host.view.translatesAutoresizingMaskIntoConstraints = false
secure.addSubview(host.view)
NSLayoutConstraint.activate([
host.view.topAnchor.constraint(equalTo: secure.topAnchor),
host.view.bottomAnchor.constraint(equalTo: secure.bottomAnchor),
host.view.leadingAnchor.constraint(equalTo: secure.leadingAnchor),
host.view.trailingAnchor.constraint(equalTo: secure.trailingAnchor),
])
return secure
}
func updateUIView(_ uiView: UIView, context: Context) { }
}
private struct CaptureProtected: ViewModifier {
func body(content: Content) -> some View {
content
.hidden()
.overlay { _CaptureProtectedContainer(content: content) }
}
}
extension View {
func captureProtected() -> some View { modifier(CaptureProtected()) }
}