How to disable pasting in a TextField in Swift?

后端 未结 14 1334
予麋鹿
予麋鹿 2020-11-30 03:41

I\'ve got a TextField with a numberPad and the function runs only if it contains numbers.

The user will crash the app if they paste letters

相关标签:
14条回答
  • 2020-11-30 04:01

    I have created a custom class for textField. I have handled the case when you want to enable/disable actions on textfield. You can customize the code as per your requirement. Set isActionsEnabled true/false for enable/disable actions on textfield.

    Prefer to use

    return super.canPerformAction(action, withSender: sender)

    instead of

    return true

    because returning true might cause a crash in some cases.

    Here is my code,

    open class MyTextFieldEffect : UITextField {
    
        var isActionsEnabled = true {
            didSet {
                reloadInputViews()
            }
        }
    
    override open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
            /* disable particular actions
            if (action == #selector(paste(_:)) || action == #selector(copy(_:)) || action == #selector(select(_:)) || action == #selector(cut(_:)) || action == #selector(delete(_:)) || action == #selector(replace(_:withText:))  || action == #selector(select(_:))  || action == #selector(selectAll(_:)) || action == #selector(insertText(_:)) || action == #selector(draw(_:))) && !isActionsEnabled {
                return false
            }
            return super.canPerformAction(action, withSender: sender)
                                               */
    
           //disable all actions
            if !isActionsEnabled {
                return false
            }
    
            return super.canPerformAction(action, withSender: sender)
        }
    }
    
    0 讨论(0)
  • 2020-11-30 04:01

    Small edit with a code because when you try to use any function like cut or another one the app will crash . The following code tested on swift 3 and working very well

    override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
            if action == #selector(copy(_:)) || action == #selector(paste(_:)) {
                return false
            }
            return super.canPerformAction(action, withSender: sender)
        }
    
    0 讨论(0)
  • 2020-11-30 04:01

    I did use this code. This is working.

    override func canPerformAction(_ action: Selector, withSender sender: Any?)  Bool {
    
        if YOURTEXTFIELD.isFirstResponder {
            DispatchQueue.main.async(execute: {
                (sender as? UIMenuController)?.setMenuVisible(false, animated: false)
            })
            return false
        }
    
        return super.canPerformAction(action, withSender: sender)
    }
    
    0 讨论(0)
  • 2020-11-30 04:06

    You can create an extension for UITextField and override canPerformAction:

    override public func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
            return (action != "paste:") 
    }
    
    0 讨论(0)
  • 2020-11-30 04:08

    Details

    • Xcode 9.1, Swift 4
    • Xcode 10.2 (10E125), 11.2 (11B52), Swift 5

    Solution 1

    // class TextField: UITextField
    extension UITextField {
    
        open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
            return action == #selector(UIResponderStandardEditActions.cut) || action == #selector(UIResponderStandardEditActions.copy)
        }
    }
    

    Solution 1 usage

    let textField = UITextField(frame: CGRect(x: 50, y: 120, width: 200, height: 50))
    textField.borderStyle = .roundedRect
    view.addSubview(textField)
    

    Solution 2

    import UIKit
    
    // MARK: Enable/Disable textfield longpress actions
    
    enum ResponderStandardEditActions {
        case cut, copy, paste, select, selectAll, delete
        case makeTextWritingDirectionLeftToRight, makeTextWritingDirectionRightToLeft
        case toggleBoldface, toggleItalics, toggleUnderline
        case increaseSize, decreaseSize
    
        var selector: Selector {
            switch self {
                case .cut:
                    return #selector(UIResponderStandardEditActions.cut)
                case .copy:
                    return #selector(UIResponderStandardEditActions.copy)
                case .paste:
                    return #selector(UIResponderStandardEditActions.paste)
                case .select:
                    return #selector(UIResponderStandardEditActions.select)
                case .selectAll:
                    return #selector(UIResponderStandardEditActions.selectAll)
                case .delete:
                    return #selector(UIResponderStandardEditActions.delete)
                case .makeTextWritingDirectionLeftToRight:
                    return #selector(UIResponderStandardEditActions.makeTextWritingDirectionLeftToRight)
                case .makeTextWritingDirectionRightToLeft:
                    return #selector(UIResponderStandardEditActions.makeTextWritingDirectionRightToLeft)
                case .toggleBoldface:
                    return #selector(UIResponderStandardEditActions.toggleBoldface)
                case .toggleItalics:
                    return #selector(UIResponderStandardEditActions.toggleItalics)
                case .toggleUnderline:
                    return #selector(UIResponderStandardEditActions.toggleUnderline)
                case .increaseSize:
                    return #selector(UIResponderStandardEditActions.increaseSize)
                case .decreaseSize:
                    return #selector(UIResponderStandardEditActions.decreaseSize)
            }
        }
    }
    
    class TextField: UITextField {
    
        private var editActions: [ResponderStandardEditActions: Bool]?
        private var filterEditActions: [ResponderStandardEditActions: Bool]?
    
        func setEditActions(only actions: [ResponderStandardEditActions]) {
            if self.editActions == nil { self.editActions = [:] }
            filterEditActions = nil
            actions.forEach { self.editActions?[$0] = true }
        }
    
        func addToCurrentEditActions(actions: [ResponderStandardEditActions]) {
            if self.filterEditActions == nil { self.filterEditActions = [:] }
            editActions = nil
            actions.forEach { self.filterEditActions?[$0] = true }
        }
    
        private func filterEditActions(actions: [ResponderStandardEditActions], allowed: Bool) {
            if self.filterEditActions == nil { self.filterEditActions = [:] }
            editActions = nil
            actions.forEach { self.filterEditActions?[$0] = allowed }
        }
    
        func filterEditActions(notAllowed: [ResponderStandardEditActions]) {
            filterEditActions(actions: notAllowed, allowed: false)
        }
    
        func resetEditActions() { editActions = nil }
    
        open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
            if let actions = editActions {
                for _action in actions where _action.key.selector == action { return _action.value }
                return false
            }
    
            if let actions = filterEditActions {
                for _action in actions where _action.key.selector == action { return _action.value }
            }
    
            return super.canPerformAction(action, withSender: sender)
        }
    }
    

    Solution 2 usage

    let textField = TextField(frame: CGRect(x: 50, y: 50, width: 200, height: 50))
    textField.borderStyle = .roundedRect
    view.addSubview(textField)
    textField.setEditActions(only: [.copy, .cut, .paste])
    //textField.filterEditActions(notAllowed: [.copy, .cut, .paste])
    //textField.addToCurrentEditActions(actions: [.paste])
    

    Full sample of the solution 2

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            addTextField(y: 50)
            addTextField(y: 100).setEditActions(only: [.copy, .cut, .paste])
            addTextField(y: 150).filterEditActions(notAllowed: [.copy, .cut, .paste])
        }
    
       @discardableResult func addTextField(y: CGFloat) -> TextField {
            let textField = TextField(frame: CGRect(x: 50, y: y, width: 200, height: 34))
            textField.borderStyle = .roundedRect
            textField.text = "Text"
            view.addSubview(textField)
            return textField
        }
    }
    
    0 讨论(0)
  • 2020-11-30 04:09

    In the actual swift version(2.2 going to 3.0) this function code must be refactored to:

    override public func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        if action == #selector(NSObject.copy(_:)) || action == #selector(NSObject.paste(_:)) {
            return false
        }
    
        return true
    }
    
    0 讨论(0)
提交回复
热议问题