Как отключить вставку в текстовое поле в Swift?

У меня есть TextField с цифровым полем, и функция запускается только если оно содержит цифры.

Единственный вариант, при котором у пользователя произойдет сбой приложения, это если он вставит буквы в TextField и нажмет OK.

Как я могу отключить вставку букв в текстовое поле?

Комментарии к вопросу (2)

Для Свифт 3 Она's изменило на:

override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    if action == #selector(copy(_:)) || action == #selector(paste(_:)) {
        return false
    }

    return true
}
Комментарии (5)
Решение

Я согласен с Leonardo Savio Dabus, на вашем месте я бы использовал проверку строк и просто выдавал предупреждение, это упрощает работу. НО, если отключение опции вставки - это причудливая функция, которую вы действительно хотите внедрить в свое приложение, тогда вам нужно проделать больше работы. Ниже я приведу шаги.

Шаг 1: Вам нужно создать другой класс, который расширяет UITextField. В этом примере я создал свой CustomUITextField.

import Foundation
import UIKit  // don't forget this

class CustomUITextField: UITextField {
    override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        if action == "paste:" {
            return false
        }        
        return super.canPerformAction(action, withSender: sender)
    }
}

Шаг 2: Соедините раскадровку с вашим ViewController. Вам нужно объявить IBOutlet, как в обычном случае:

@IBOutlet var textFieldA: CustomUITextField?

Подключите круг рядом с @IBOutlet к текстовому полю в раскадровке. ИТОГ: это важно, и это легко проигнорировать:

  • Перейдите к вашей раскадровке
  • Нажмите на целевое текстовое поле
  • Выберите Identity Inspector (3-й).
  • Измените класс на CustomUITextField

Ниже приведен быстрый снимок.

Вот и все, надеюсь, это работает.

Credit:

В основном ссылка с https://teamtreehouse.com/forum/disable-paste-in-uitextfielduitextview-swift

Если вы хотите узнать больше о поведении метода canPerformAction, хотя это версия objective-C, но концепции общие: https://stackoverflow.com/questions/20223966/how-can-i-detect-that-a-user-has-tapped-a-formatting-button-in-a-uimenucontrolle

Комментарии (2)

Для Свифт 5

UIResponderStandardEditActions был добавлен недавно (прошивкой 10.0+) с помощью которых можно надежно проверить, если есть "вставить" или нет.

import UIKit

class NMTextField: UITextField {
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if action == #selector(UIResponderStandardEditActions.paste(_:)) {
            return false
        }
        return super.canPerformAction(action, withSender: sender)
    }
}
Комментарии (0)

Детали #

  • В Xcode 9.1, Свифт 4
  • В Xcode 10.2 (10E125), 11.2 (11B52), Свифт 5

Решение 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)
    }
}

Решение 1 Использование

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

Решение 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)
    }
}

Решение# 2 #Использование

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])

Полный образец решение 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
    }
}
Комментарии (1)

Свифт 4.1 этот код работает нормально в файле ViewController.

  1. Отключить все опции (копирование, вставка, удаление.....и т. д.)
extension UITextField {

    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return false
    }
}
  1. включить конкретной опции (выбрать, selectAll... и т. д.)
extension UITextField {

open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    return action == #selector(UIResponderStandardEditActions.select(_:)) || action == #selector(UIResponderStandardEditActions.selectAll(_:))
}
Комментарии (1)

В реальной Свифт версию(2.2 собирается 3.0) этот код функции должен быть преобразована в:

override public func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
    if action == #selector(NSObject.copy(_:)) || action == #selector(NSObject.paste(_:)) {
        return false
    }

    return true
}
Комментарии (1)

Вы можете создать расширение для UITextField и переопределить canPerformAction:

override public func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool {
        return (action != "paste:") 
}
Комментарии (2)

Вы можете просто прикрепить IBAction к Sent Events (редактирование изменено) вашего текстового поля, чтобы отфильтровать не-числа из вашей строки по мере ввода, как показано ниже:

@IBAction func changedTextAction(sender: UITextField) {
    sender.text = String(Array(sender.text).map{String($0)}.filter{ $0.toInt() != nil }.map{Character($0)} )
}
Комментарии (0)
class CustomUITextField: UITextField {
    override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        if action == #selector(cut(_:)) ||
           action == #selector(copy(_:)) ||  
           action == #selector(UIResponderStandardEditActions.paste(_:)) || 
           action == #selector(UIResponderStandardEditActions.select(_:)) || 
           action == #selector(UIResponderStandardEditActions.selectAll(_:)) || 
           action == #selector(UIResponderStandardEditActions.delete(_:)) ||  
           action == #selector(UIResponderStandardEditActions.makeTextWritingDirectionLeftToRight(_:)) ||  
           action == #selector(UIResponderStandardEditActions.makeTextWritingDirectionRightToLeft(_:)) || 
           action == #selector(UIResponderStandardEditActions.toggleBoldface(_:)) || 
           action == #selector(UIResponderStandardEditActions.toggleItalics(_:)) || 
           action == #selector(UIResponderStandardEditActions.toggleUnderline(_:)) || 
           action == #selector(UIResponderStandardEditActions.increaseSize(_:)) || 
           action == #selector(UIResponderStandardEditActions.decreaseSize(_:)) 
        {
             return false
        };
        return true
    }
}
Комментарии (1)

Я создал пользовательский класс для textfield. Я обработал случае, когда вы хотите включить/отключить действия на поле. Вы можете настроить код согласно вашему требованию. Набор isActionsEnabled true или false для включения/выключения действия на поле.

Предпочитают использовать

возвращение супер.canPerformAction(действий, withSender: отправителя)

вместо

возвращать true

потому что возвращая True может вызвать сбой в некоторых случаях.

Вот мой код,

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)

Если вы хотите открыть дата выбора или посмотреть комплектовщик на поле нажмите затем ниже код работы.

Добавить ниже два метода в своем классе.

//Hide Menu View
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)
}

//Должен реализовать

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
            return false
}
Комментарии (0)

Небольшие изменения в код, потому что при попытке использовать любую функцию как вырезать или еще одно приложение рухнет . Следующий код протестирован на Свифт 3 и очень хорошо работает

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)