Пользовательский вид ввода в Swift

Я часами пытался понять, как создать/затем заставить работать пользовательский inputView. У меня есть сетка TextInputs (например, доска для рисования), которая при нажатии должна загружать пользовательский inputView для вставки текста.

Я создал файл .xib, содержащий UI elements для пользовательского inputView. Мне удалось создать CustomInputViewController и отобразить inputView, но я так и не смог заставить фактический TextInput обновить его значение/текст.

Документация Apple показалась легкой в ​​том, как заставить это работать, и во многих учебниках, которые я видел, использовался Obj-C (который я не смог преобразовать из-за мелких вещей, которые, похоже, теперь невозможно сделать быстро) .

Какова всеобъемлющая архитектура и необходимые фрагменты кода, которые необходимо реализовать для создания customInputView для нескольких textInputs (цепочка делегатов, контроллер, .xibs, представления и т. д.)?


person codycoats    schedule 28.10.2014    source источник
comment
Создайте пользовательский файл класса и установите его как класс для вашего xib в InterfaceBuilder. Затем вы можете перетащить элементы пользовательского интерфейса, удерживая нажатой клавишу Ctrl, в файл класса (помощник редактора), чтобы создать IBOutlets. Используйте эти выходы в своем коде для обновления элементов пользовательского интерфейса.   -  person zisoft    schedule 28.10.2014
comment
Мне удалось создать IBOutlets/IBActions для кнопок в customView. Это было необходимо, но недостаточно, чтобы кнопки в customView передавали textInput/keyboardFunctionality представлению TextInputs.   -  person codycoats    schedule 28.10.2014
comment
разве ваши взгляды не должны реализовываться/соответствовать правильному протоколу? (UITextInput?). возможно, вам также придется сказать им, чтобы они первыми реагировали, когда их прослушивают. Я бы попробовал создать подкласс UIControl против UIView.   -  person nielsbot    schedule 14.02.2015
comment
взгляните на это: stackoverflow .com/questions/26539849/.   -  person Abdullah Md. Zubair    schedule 17.02.2015


Ответы (2)


Вы не должны проходить через все эти хлопоты. В iOS 8 появился новый класс под названием: UIAlertController, где вы можете добавить TextFields для ввода пользователем данных. Вы можете оформить его как Alert или ActionSheet.

Пример:

let alertAnswer = UIAlertController(title: "Input your scrabble Answer", message: nil, preferredStyle: .Alert) // or .ActionSheet

Теперь, когда у вас есть контроллер, добавьте к нему поля:

alertAnswer.addTextFieldWithConfigurationHandler { (get) -> Void in
            getAnswer.placeholder = "Answer"
            getAnswer.keyboardType = .Default
            getAnswer.clearsOnBeginEditing = true
            getAnswer.borderStyle = .RoundedRect
        } // add as many fields as you want with custom tweaks

Добавьте кнопки действий:

let submitAnswer = UIAlertAction(title: "Submit", style: .Default, handler: nil)
let cancel = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
alertAnswer.addAction(submitAnswer)
alertAnswer.addAction(cancel)

Подарите контроллер, когда захотите, с помощью:

self.presentViewController(alertAnswer, animated: true, completion: nil)

Как видите, у вас есть различные обработчики для передачи пользовательского кода на любом этапе.

Например, вот как это могло бы выглядеть: Пример того, как это могло бы выглядеть

person leonardo    schedule 15.02.2015

Настройте файл пера с соответствующим макетом и элементами inputView. В моем случае я установил для каждой кнопки действие владельца файла inputViewButtonPressed.

Настройте раскадровку (или перо, если хотите) для контроллера представления.

Затем, используя следующий код, вы должны получить то, что ищете:

class ViewController: UIViewController, UITextFieldDelegate {
    var myInputView : UIView!
    var activeTextField : UITextField?

    override func viewDidLoad() {
        super.viewDidLoad()

        // load input view from nib
        if let objects = NSBundle.mainBundle().loadNibNamed("InputView", owner: self, options: nil) {
            myInputView = objects[0] as UIView
        }

        // Set up all the text fields with us as the delegate and
        // using our input view
        for view in self.view.subviews {
            if let textField = view as? UITextField {
                textField.inputView = myInputView
                textField.delegate = self
            }
        }
    }

    func textFieldDidBeginEditing(textField: UITextField) {
        activeTextField = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        activeTextField = nil
    }

    @IBAction func inputViewButtonPressed(button:UIButton) {
        // Update the text field with the text from the button pressed
        activeTextField?.text = button.titleLabel?.text

        // Close the text field
        activeTextField?.resignFirstResponder()
    }
}

В качестве альтернативы, если вы хотите быть более похожим на клавиатуру, вы можете использовать эту функцию в качестве своего действия (она использует новый синтаксис let из Swift 1.2), разбейте ее, если вам нужна совместимость с 1.1:

    @IBAction func insertButtonText(button:UIButton) {
        if let textField = activeTextField, title = button.titleLabel?.text, range = textField.selectedTextRange {
            // Update the text field with the text from the button pressed
            textField.replaceRange(range, withText: title)
        }
    }

При этом используется протокол UITextInput для обновления текстового поля по мере необходимости. Обработка удаления немного сложнее, но все же не так уж плохо:

    @IBAction func deleteText(button:UIButton) {
        if let textField = activeTextField, range = textField.selectedTextRange {
            if range.empty {
                // If the selection is empty, delete the character behind the cursor
                let start = textField.positionFromPosition(range.start, inDirection: .Left, offset: 1)
                let deleteRange = textField.textRangeFromPosition(start, toPosition: range.end)
                textField.replaceRange(deleteRange, withText: "")
            }
            else {
                // If the selection isn't empty, delete the chars in the selection
                textField.replaceRange(range, withText: "")
            }
        }
    }
person David Berry    schedule 17.02.2015
comment
Большое спасибо за этот ответ, Дэвид. Если бы я хотел повторно использовать клавиатуру в нескольких местах, что бы вы порекомендовали как лучший способ сделать это? - person Richard Burton; 14.03.2015
comment
Вы можете создать подкласс UIViewController или создать экземпляр этого кода либо в подклассе UITextField, либо в отдельном классе контроллера. - person David Berry; 14.03.2015