iOS:禁止螢幕截圖

Photo by Svitlana on Unsplash
Photo by Svitlana on Unsplash
基於一些理由,我們可能會想要禁止使用者對我們的 app 做螢幕截圖。然而,iOS 並沒有提供這樣的功能。所幸,我們可以利用 UITextField 來達到此效果。

基於一些理由,我們可能會想要禁止使用者對我們的 app 做螢幕截圖。然而,iOS 並沒有提供這樣的功能。所幸,我們可以利用 UITextField 來達到此效果。

當將 UITextField.isSecureTextEntry 設為 true 之後,若使用者做螢幕截圖時,iOS UITextField 會將它的內容清空,來保護其內容不被截圖。因此,若我們將當前的 view 放進 UITextField,那當使用者做螢幕截圖時,UITextField 將會防止當前的 view 被截圖下來,如下程式碼(此程式碼源自於這裡)。

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.makeSecure()
    }
}

extension UIView {
    func makeSecure() {
        DispatchQueue.main.async {
            let field = UITextField()
            field.isSecureTextEntry = true
            self.addSubview(field)
            field.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
            field.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
            self.layer.superlayer?.addSublayer(field.layer)
            field.layer.sublayers?.first?.addSublayer(self.layer)
        }
    }
}

當我們用以上的程式碼保護當前的 view 之後,若使用者對此 view 做螢幕截圖的話,那他只會得到一個全部都是黑色的圖。

在使用 makeSecure() 保護 view 之後,你也可以隨時用 makeInsecure() 來取消保護此 view,如下程式碼。

class ViewController: UIViewController {
    @IBAction func onClick(_ sender: Any) {
        view.makeInsecure()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.makeSecure()
    }
}

var textField: UITextField?

extension UIView {
    func makeSecure() {
        DispatchQueue.main.async {
            let field = UITextField()
            field.isSecureTextEntry = true
            self.addSubview(field)
            field.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
            field.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
            self.layer.superlayer?.addSublayer(field.layer)
            field.layer.sublayers?.first?.addSublayer(self.layer)
            
            textField = field
        }
    }
    
    func makeInsecure() {
        DispatchQueue.main.async {
            guard let field = textField else { return }
            textField = nil
            field.layer.superlayer?.addSublayer(self.layer)
            field.removeFromSuperview()
            field.layer.removeFromSuperlayer()
        }
    }
}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

You May Also Like
Photo by Alex Alvarez on Unsplash
Read More

Dispatch Queue 教學

GCD 提供有效率的並行處理,讓我們不需要直接管理多執行緒。它的 Dispatch Queues 可以循序地(serially)或是並行地(concurrently)執行任務。我們只需要將要並行的程式當作任務提交到 dispatch queues 就可以了。
Read More
Photo by Florinel Gorgan on Unsplash
Read More

如何製作一個 XCFramework

XCFramework 讓你可以將 iPhone、iPhone 模擬器等多的不同平台的二進位碼打包到一個可發佈的 .xcframework 檔。你只需要為你的 Framework 產生出一個 .xcframework 檔,就可以支援多種平台。
Read More
Photo by Fabian Gieske on Unsplash
Read More

SwiftUI @State & @Binding 教學

SwiftUI 推出了兩個 Property Wrapper – @State and @Binding。利用它們可以達到變數的 Two-way Binding 功能。也就是當變數的值改變時,它會重新被顯示。本章藉由製作一個 Custom View 來展示如何使用 @State 和 @Binding。
Read More