Can we disable copy/paste options of Textfield in SwiftUI?
Asked Answered
M

3

15

I want to disable the option of copy/paste from my Textfield in SwiftUI. How to achieve that?

Marsh answered 10/2, 2020 at 10:33 Comment(1)
I don't believe it is possible in SwiftUI TextField for now, you should use UITextField instead by conform to UIViewRepresentableLaborsaving
S
5

This works for me:

  • Using UITextField conforms to UIViewRepresentable.
import SwiftUI

struct ContentView: View {
    
    @State private var text = ""
    
    var body: some View {
        VStack {
            Text(text)
            UITextFieldViewRepresentable(text: $text) // Using it
                .frame(height: 44)
                .border(.red)
        }
    }
}

// MARK: UITextFieldViewRepresentable
struct UITextFieldViewRepresentable: UIViewRepresentable {
    
    @Binding var text: String
    typealias UIViewType = ProtectedTextField
    
    
    func makeUIView(context: Context) -> ProtectedTextField {
        let textField = ProtectedTextField()
        textField.delegate = context.coordinator
        return textField
    }
    
    // From SwiftUI to UIKit
    func updateUIView(_ uiView: ProtectedTextField, context: Context) {
        uiView.text = text
    }
    
    // From UIKit to SwiftUI
    func makeCoordinator() -> Coordinator {
        return Coordinator(text: $text)
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        @Binding var text: String
        
        init(text: Binding<String>) {
            self._text = text
        }
        
        func textFieldDidChangeSelection(_ textField: UITextField) {
            text = textField.text ?? ""
        }
    }
}

// Custom TextField with disabling paste action
class ProtectedTextField: UITextField {
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        
        if action == #selector(paste(_:)) {
            return false
        }
        return super.canPerformAction(action, withSender: sender)
    }
}
Sparge answered 10/11, 2022 at 16:39 Comment(0)
D
2

Use UIViewRepresentable class make wrapper class like this.

import SwiftUI

struct CustomeTextField: View {

    @State var textStr = ""


    var body: some View {
        VStack(spacing: 10) {
            Text("This is textfield:")
                .font(.body)
                .foregroundColor(.gray)

            TextFieldWrapperView(text: self.$textStr)
                .background(Color.gray)
                .frame(width: 200, height: 50)
        }
        .frame(height: 40)
    }
}


struct TextFieldWrapperView: UIViewRepresentable {

    @Binding var text: String

    func makeCoordinator() -> TFCoordinator {
        TFCoordinator(self)
    }
}

extension TextFieldWrapperView {


    func makeUIView(context: UIViewRepresentableContext<TextFieldWrapperView>) -> UITextField {
        let textField = UITextField()
        textField.delegate = context.coordinator
        return textField
    }


    func updateUIView(_ uiView: UITextField, context: Context) {

    }
}

class TFCoordinator: NSObject, UITextFieldDelegate {
    var parent: TextFieldWrapperView

    init(_ textField: TextFieldWrapperView) {
        self.parent = textField
    }

    func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        if action == #selector(UIResponderStandardEditActions.paste(_:)) {
            return false
        }
        return canPerformAction(action: action, withSender: sender)
    }
}
Dentoid answered 10/2, 2020 at 12:38 Comment(2)
Nice, this is very useful to intercept paste actions while the user also has an image on their clipboardJudicature
canPerformAction not getting called. Why?Levite
M
-1

Not the complete answer to this question but some may find it useful, you can use SwiftUI SecureField to disable copy, but not paste.

Mcauley answered 7/8 at 0:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.