Ios 用于数据输入的自定义视图的Swift示例(自定义应用程序内键盘) 目标

Ios 用于数据输入的自定义视图的Swift示例(自定义应用程序内键盘) 目标,ios,swift,keyboard,custom-keyboard,Ios,Swift,Keyboard,Custom Keyboard,我想制作一个只在我的应用程序中使用的自定义键盘,而不是需要安装的系统键盘 我读过并尝试过的东西 文档 上述第一条规定: 确保定制的全系统键盘确实是您想要的 发展为您的应用程序提供完全定制的键盘,或 仅在应用程序中使用自定义键补充系统键盘 iOS SDK提供了其他更好的选项。了解自定义输入视图 并在自定义视图中输入附件视图,以便在文本中输入数据 iOS编程指南 这就是我读到上面第二篇文章的原因。然而,那篇文章没有足够的细节让我开始 教程 我能够从上面列表中的第二个教程中获得一个

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

我读过并尝试过的东西 文档

上述第一条规定:

确保定制的全系统键盘确实是您想要的 发展为您的应用程序提供完全定制的键盘,或 仅在应用程序中使用自定义键补充系统键盘 iOS SDK提供了其他更好的选项。了解自定义输入视图 并在自定义视图中输入附件视图,以便在文本中输入数据 iOS编程指南

这就是我读到上面第二篇文章的原因。然而,那篇文章没有足够的细节让我开始

教程

我能够从上面列表中的第二个教程中获得一个工作键盘。但是,我找不到任何教程来演示如何按照文档中的描述制作仅应用程序内的键盘

堆栈溢出

在回答当前问题的过程中,我也问了(并回答了)这些问题

问题: 是否有人有一个应用程序内自定义键盘的最小示例(甚至只有一个按钮)?我不是在寻找一个完整的教程,只是一个概念证明,我可以扩展自己。

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

  • 在.xib文件中创建键盘布局,其所有者是包含
    UIView
    子类的.swift文件
  • 告诉
    UITextField
    使用自定义键盘
  • 使用代理在键盘和主视图控制器之间进行通信
创建.xib键盘布局文件
  • 在Xcode中转到文件>新建>文件…>iOS>用户界面>查看以创建.xib文件
  • 我叫我的键盘.xib
  • 添加您需要的按钮
  • 使用自动布局约束,以便无论键盘大小如何,按钮都将相应调整大小
  • 将文件的所有者(不是根视图)设置为Keyboard.swift文件。这是常见的错误源。见最后的注释
创建.swift UIView子类键盘文件
  • 在Xcode中转到文件>新建>文件…>iOS>Source>Cocoa Touch类创建.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 = Bundle.main.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文件中的按钮拖动到.swift文件中的
    @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_访问错误,可能是因为您将视图的自定义类设置为Keyboard.swift,而不是为nib文件的所有者执行此操作

选择Keyboard.nib,然后选择文件的所有者

确保根视图的自定义类为空


根据苏拉奇的回答,我需要一个“完成”和“退格”按钮,如果你是像我这样的傻瓜,这里有一些你可能会遇到的错误以及我解决这些错误的方法

获取EXC\u错误\u访问错误? 我包括:

@objc(classname)
class classname: UIView{ 
}
修复了我的问题,但是Suragch的更新答案似乎以更合适/正确的方式解决了这个问题

获取SIGABRT错误? 另一件愚蠢的事情是以错误的方式拖动连接,导致SIGABRT错误。不要从函数拖动到按钮,而是将按钮拖动到函数

添加完成按钮 我在keyboard.swift中将此添加到协议中:

protocol KeyboardDelegate: class {
    func keyWasTapped(character: String)
    func keyDone()
}
然后将一个新iAction从“我的完成”按钮连接到键盘。如下所示:

@IBAction func Done(sender: UIButton) {
    self.delegate?.keyDone()
}
然后跳回我的viewController.swift,在这里我使用这个键盘,并在点击功能键后添加了以下内容:

func keyDone() {
    view.endEditing(true)
}
添加退格 这让我大吃一惊,因为必须在viewDidLoad()方法(稍后显示)中将textField.delegate设置为self

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

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

@IBAction func backspace(sender: UIButton) {
    self.delegate?.backspace()
}
第三:转到viewController.swift,其中出现了NumberPad

重要提示:在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
}
var activeTextField = UITextField()

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

func backspace() {
    print("backspaced!")
    activeTextField.deleteBackward()
}
我不知道如何,如果有一种方法可以对视图中的所有文本字段执行此操作的话。这会很方便

第四:仍然在viewController.swift中,我们需要添加一个变量和两个函数。它将如下所示:

 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
}
var activeTextField = UITextField()

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

func backspace() {
    print("backspaced!")
    activeTextField.deleteBackward()
}
解释此处发生的情况:

  • 您可以创建一个包含文本字段的变量
  • 当调用“textFieldDidBeginEditing”时,它会设置变量,以便知道我们正在处理哪个textField。我已经添加了很多打印件(),所以我们知道一切都在执行中
  • 然后,我们的backspace函数检查正在处理和使用的textField.deleteBackward()。这将删除光标前的直接字符
  • 你应该做生意。
    非常感谢Suragchs帮助我实现这一点。

    关键是使用现有的协议,
    UITextField
    已经符合该协议。然后您的键盘视图需要
    textField.inputView = NumericKeyboard(target: textField)
    
    textField.inputView = NumericKeyboard(target: textField, useDecimalSeparator: true)