Swift 带有集合视图的慢速自定义键盘按钮

Swift slow custom keyboard buttons with collectionviews

免责声明:

在你把我的脑袋砍下来放火之前,我知道已经有人问过这样的问题,但它们都指的是单个按钮我有一个 collectionView。在仔细阅读所有其他问题并尝试将他们的解决方案结合在一起之后,我才问这个问题。

概览:

我正在创建一个带有集合视图的键盘扩展。在我的 collectionView 中,我有自定义单元格,在它们的 class 中,我放置了一个按钮。我想为集合视图中的每个按钮添加一个目标。我知道我可以使用 selectItemAtIndexRow 函数并忽略按钮,但我需要处理 touchUpInside 和 touchDown 事件(因为当我使用 y 键盘键入时它非常慢)并且我还没有找到使用 collectionView 单元格的方法(如果有些东西存在让我知道)。为了避免这个问题,我认为最好的解决方案是在我的单元格 class 中添加一个按钮并添加我想要的操作,但我发现这样做有多个问题。

我在做什么:

  1. 我有 classic 键盘ViewController 你可以通过创建一个新的键盘目标来获得,我在其中放置了一个视图(这是包含 collectionView 的视图)。

  2. 我有一个包含集合视图的自定义视图class

  3. 我有一个自定义的 collectionview 单元格 class

自定义视图Class

这里我以编程方式创建了我的 collectionView。

//Closure to add action to my buttons
 var insertLowercase : ((IndexPath) -> ())?
    
 let letters = ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"]

 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        letters.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = keyView.dequeueReusableCell(withReuseIdentifier: "collectionCellId", for: indexPath) as! KeyboardKeys
        cell.button.setTitle(letters[indexPath.row], for: .normal)
        cell.button.addTarget(self, action: #selector(lettersKeyboard.insert(indexPath:)), for: .touchUpInside)
        return cell
    }
    
    @objc func insert (indexPath: IndexPath){
        insertLowercase?(indexPath)
    }

这就是我添加目标的方式。但是,如果我按下按钮,键盘会崩溃并出现以下错误:

Thread 1: "-[Keyboarddd.KeyboardButton length]: unrecognized selector sent to instance 0x7f9bb2506740"

键盘ViewController

将我的自定义视图放在这里后,在 viewDidLoad 中我调用它:

 letters.insertLowercase = { indexPath in
            let text = self.letters.letters[indexPath.row]
            self.textDocumentProxy.insertText(text)
        } //And more stuff to handle quick insertion but this is what you need to reproduce my problem

问题:

如何正确地将目标添加到我的按钮中?或者有没有办法直接对 collectionView 单元格执行我想执行的操作?

您的问题是 UIButton.addTarget 没有调用将 IndexPath 作为参数的方法。通常,您所做的是处理单元格中的按钮操作,然后在按下按钮时调用回调。

class KeyboardKeys: UICollectionViewCell {

    @IBOutlet weak var button: UIButton! {
        didSet {
            button.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside)
        }
    }

    var didPushButton: (KeyboardKeys) -> Void = { _ in }

    @objc func buttonAction(_ button: UIButton) {
        didPushButton(self)
    }
}

在您的数据源方法中,您想为每个单元格注册一个回调:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellId", for: indexPath) as! KeyboardKeys
    cell.button.setTitle(letters[indexPath.row], for: .normal)
    cell.didPushButton = { [weak self] cell in
        guard let indexPath = collectionView.indexPath(for: cell) else { return }
        self?.insert(indexPath: indexPath)
    }
    return cell
}