数据input自定义视图的Swift示例(自定义应用程序内键盘)

目标

我想制作一个只在我的应用程序中使用的自定义键盘,而不是需要安装的系统键盘。

我已阅读和尝试

文档

  • 应用程序扩展编程指南:自定义键盘
  • 数据input的自定义视图

上面的第一篇文章指出:

确保一个自定义的系统范围的键盘确实是你想要开发的。 要为您的应用程序提供完全自定义的键盘,或仅在应用程序中使用自定义键来补充系统键盘,iOS SDK提供了其他更好的选项。 在iOS的文本编程指南中阅读自定义input视图和input用于数据input的自定义视图中的附件视图。

这就是我所说的第二篇文章。 不过,那篇文章没有足够的细节让我开始。

教程

  • iOS 8:在Swift中创build自定义键盘
  • 如何使用Swift在iOS 8中制作自定义键盘
  • Xcode 6教程:iOS 8.0 Swift中简单的自定义键盘
  • 使用iOS 8应用程序扩展创build自定义键盘

我可以从上面的列表中的第二个教程中获得一个可用的键盘。 但是,我找不到任何教程展示了如何在数据input自定义视图文档中介绍如何创build应用程序内置键盘。

堆栈溢出

我在回答当前问题的途中也问了(并回答了)这些问题。

  • 如何使用应用内自定义键盘的buttoninput文本
  • 代表在Swift中

有没有人有一个最小的例子(甚至一个button)的应用程序自定义键盘? 我不是在寻找一个完整的教程,只是一个我可以自己展开的概念certificate。

在这里输入图像描述

这是一个基本的应用程序内键盘。 同样的方法可以用来做任何键盘布局。 以下是需要做的主要事情:

  • 在.xib文件中创build键盘布局,其所有者是包含UIView子类的.swift文件。
  • 告诉UITextField使用自定义键盘。
  • 使用委托在键盘和主视图控制器之间进行通信。

创build.xib键盘布局文件

  • 在Xcode中,进入文件>新build>文件…> iOS>用户界面>视图来创build.xib文件。
  • 我叫我的Keyboard.xib
  • 添加你需要的button。
  • 使用自动布局约束,以便无论键盘的大小如何,button都会相应地resize。
  • 将文件的所有者(而不是根视图)设置为Keyboard.swift文件。 这是一个常见的错误来源。 看最后的说明。

创build.swift UIView子类键盘文件

  • 在Xcode转到文件>新build>文件…> iOS>源>cocoa触摸类创build.swift文件。
  • 我打电话给我的Keyboard.swift
  • 添加下面的代码:

     import UIKit // The view controller will adopt this protocol (delegate) // and thus must contain the keyWasTapped method protocol KeyboardDelegate: class { func keyWasTapped(character: String) } class Keyboard: UIView { // This variable will be set as the view controller so that // the keyboard can send messages to the view controller. weak var delegate: KeyboardDelegate? // MARK:- keyboard initialization required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) initializeSubviews() } override init(frame: CGRect) { super.init(frame: frame) initializeSubviews() } func initializeSubviews() { let xibFileName = "Keyboard" // xib extention not included let view = NSBundle.mainBundle().loadNibNamed(xibFileName, owner: self, options: nil)[0] as! UIView self.addSubview(view) view.frame = self.bounds } // MARK:- Button actions from .xib file @IBAction func keyTapped(sender: UIButton) { // When a button is tapped, send that information to the // delegate (ie, the view controller) self.delegate?.keyWasTapped(character: sender.titleLabel!.text!) // could alternatively send a tag value } } 
  • 控制.xib文件中的button拖动到@IBAction文件中的@IBAction方法,以将它们全部挂钩。

  • 请注意协议和委托代码。 看到这个答案是关于代表如何工作的一个简单的解释。

设置视图控制器

  • 添加一个UITextField到你的主故事板,并用IBOutlet将它连接到你的视图控制器。 把它叫做textField
  • 对视图控制器使用以下代码:

     import UIKit class ViewController: UIViewController, KeyboardDelegate { @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() // initialize custom keyboard let keyboardView = Keyboard(frame: CGRect(x: 0, y: 0, width: 0, height: 300)) keyboardView.delegate = self // the view controller will be notified by the keyboard whenever a key is tapped // replace system keyboard with custom keyboard textField.inputView = keyboardView } // required method for keyboard delegate protocol func keyWasTapped(character: String) { textField.insertText(character) } } 
  • 请注意,视图控制器采用我们上面定义的KeyboardDelegate协议。

常见错误

如果您收到EXC_BAD_ACCESS错误,可能是因为您将视图的自定义类设置为Keyboard.swift,而不是为nib文件的所有者执行此操作。

selectKeyboard.nib,然后select文件的所有者。

在这里输入图像描述

确保根视图的自定义类是空白的。

在这里输入图像描述

基于Suragch的回答,我需要一个完成和退格button,如果你是像我这样的noob,那么你可能遇到的一些错误以及我解决它们的方式。

获取EXC_BAD_ACCESS错误? 我包括:

 @objc(classname) class classname: UIView{ } 

解决了我的问题,但Suragch的更新答案似乎解决这个更合适/正确的方式。

获得SIGABRT错误? 另一个愚蠢的事情是错误地拖动连接,导致SIGABRT错误。 不要从function拖到button,而是将button拖到function上。

添加完成button我将其添加到keyboard.swift中的协议:

 protocol KeyboardDelegate: class { func keyWasTapped(character: String) func keyDone() } 

然后从我的完成button连接一个新的IBAction到keyboard.swift像这样:

 @IBAction func Done(sender: UIButton) { self.delegate?.keyDone() } 

然后跳回到我的viewController.swift,我使用这个键盘,并在函数keyWasTapped后添加以下内容:

 func keyDone() { view.endEditing(true) } 

添加Backspace这让我感到非常沮丧,因为您必须在viewDidLoad()方法中将textField.delegate设置为self(稍后显示)。

首先:在keyboard.swift中添加协议func backspace():

 protocol KeyboardDelegate: class { func keyWasTapped(character: String) func keyDone() func backspace() } 

第二:连接一个新的IBAction类似于完成操作:

 @IBAction func backspace(sender: UIButton) { self.delegate?.backspace() } 

第三:到NumberPad出现的viewController.swift。

重要提示:在viewDidLoad()中设置将使用此键盘的所有文本字段。 所以你的viewDidLoad()应该看起来像这样:

  override func viewDidLoad() { super.viewDidLoad() self.myTextField1.delegate = self self.myTextField2.delegate = self // initialize custom keyboard let keyboardView = keyboard(frame: CGRect(x: 0, y: 0, width: 0, height: 240)) keyboardView.delegate = self // the view controller will be notified by the keyboard whenever a key is tapped // replace system keyboard with custom keyboard myTextField1.inputView = keyboardView myTextField2.inputView = keyboardView } 

我不知道如何,如果有办法只是这样做的视图中的所有textFields。 这将是方便的…

第四:仍然在viewController.swift中,我们需要添加一个variables和两个函数。 它看起来像这样:

 var activeTextField = UITextField() func textFieldDidBeginEditing(textField: UITextField) { print("Setting Active Textfield") self.activeTextField = textField print("Active textField Set!") } func backspace() { print("backspaced!") activeTextField.deleteBackward() } 

这里发生了什么的解释:

  1. 你做一个variables,将持有一个textField。
  2. 当调用“textFieldDidBeginEditing”时,它设置variables,以便知道我们正在处理哪个文本字段。 我添加了很多的打印(),所以我们知道一切正在执行。
  3. 我们的backspace函数然后检查我们正在处理的textField并使用.deleteBackward()。 这将删除光标前面的直接字符。

你应该做生意。 非常感谢Suragchs帮助我实现这一目标。