How to disable pasting in a TextField in Swift?

后端 未结 14 1453
予麋鹿
予麋鹿 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: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
        }
    }
    

提交回复
热议问题