Swift/iOS:如何通过点击手势判断哪款文本框成为第一响应者
优化你的文本框点击识别逻辑
嘿,我来帮你捋捋这个文本框点击的实现思路~你当前的代码虽然能跑,但存在效率低、有崩溃风险的问题,而且其实有更简洁可靠的方式来获取被点击文本框的索引!
先说说你当前代码的问题
- 强制解包风险:
(boxArray[i]?.isFirstResponder)!里的感叹号太危险了,如果数组中存在nil元素,直接就会崩溃。 - 效率低下:每次点击都要遍历100个文本框,明明我们可以直接从手势识别器拿到被点击的那个文本框,完全没必要做全量遍历。
- 冗余操作:
boxArray.index(of: boxArray[i])其实结果就是i,这一步纯纯是多此一举;而且如果数组里有重复引用的文本框(虽然你这里应该不会),还可能拿到错误的索引。
方案一:直接从手势识别器获取文本框并查找索引
这个方法更可靠,还避免了遍历全数组:
@objc func tappedTextField(_ sender: UITapGestureRecognizer) { // 先把手势绑定的View转成UITextField,失败就直接返回 guard let tappedTextField = sender.view as? UITextField else { return } // 通过对象引用匹配(===)找到对应的数组索引 if let index = boxArray.firstIndex(where: { $0 === tappedTextField }) { print("被点击的文本框索引:\(index)") } }
这里用===是为了判断两个对象是不是同一个引用,避免因为文本框内容相同导致的索引匹配错误,比用==更精准。
方案二:给手势识别器绑定索引Tag(更高效)
如果你的数组后续不会频繁增删元素,那这个方法效率最高,代码也最简洁:
首先在给文本框添加手势的时候,把数组索引赋值给手势的tag:
for (index, textField) in boxArray.enumerated() { guard let textField = textField else { continue } let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tappedTextField(_:))) tapGesture.tag = index textField.addGestureRecognizer(tapGesture) }
然后点击处理方法直接取tag就行:
@objc func tappedTextField(_ sender: UITapGestureRecognizer) { print("被点击的文本框索引:\(sender.tag)") }
这个方法省掉了数组查找的步骤,性能拉满!不过要注意,如果后续你对boxArray做了增删操作,之前绑定的tag就会和实际索引不匹配,这时候方案一更稳妥。
内容的提问来源于stack exchange,提问作者alexstrasza
相关产品推荐
相关产品推荐

