У меня есть TextField
с цифровым полем, и функция запускается только если оно содержит цифры.
Единственный вариант, при котором у пользователя произойдет сбой приложения, это если он вставит буквы в TextField
и нажмет OK.
Как я могу отключить вставку букв в текстовое поле?
Для Свифт 3 Она's изменило на:
override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(copy(_:)) || action == #selector(paste(_:)) {
return false
}
return true
}
Я согласен с 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
к текстовому полю в раскадровке. ИТОГ: это важно, и это легко проигнорировать:
Ниже приведен быстрый снимок.
Вот и все, надеюсь, это работает.
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
Для Свифт 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)
}
}
// class TextField: UITextField
extension UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return action == #selector(UIResponderStandardEditActions.cut) || action == #selector(UIResponderStandardEditActions.copy)
}
}
let textField = UITextField(frame: CGRect(x: 50, y: 120, width: 200, height: 50))
textField.borderStyle = .roundedRect
view.addSubview(textField)
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)
}
}
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])
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
}
}
Свифт 4.1 этот код работает нормально в файле ViewController.
extension UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return false
}
}
extension UITextField {
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return action == #selector(UIResponderStandardEditActions.select(_:)) || action == #selector(UIResponderStandardEditActions.selectAll(_:))
}
В реальной Свифт версию(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
}
Вы можете просто прикрепить IBAction к Sent Events (редактирование изменено) вашего текстового поля, чтобы отфильтровать не-числа из вашей строки по мере ввода, как показано ниже:
@IBAction func changedTextAction(sender: UITextField) {
sender.text = String(Array(sender.text).map{String($0)}.filter{ $0.toInt() != nil }.map{Character($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
}
}
Я создал пользовательский класс для 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)
}
}
Если вы хотите открыть дата выбора или посмотреть комплектовщик на поле нажмите затем ниже код работы.
Добавить ниже два метода в своем классе.
//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
}
Небольшие изменения в код, потому что при попытке использовать любую функцию как вырезать или еще одно приложение рухнет . Следующий код протестирован на Свифт 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)
}