Swift自定义键盘应用点击按钮崩溃,代码无报错却不生效求助
问题分析与修复方案
一、崩溃核心原因及修复
1. 避免documentContextBeforeInput强制解包
proxy.documentContextBeforeInput在无前置输入内容时会返回nil,直接用!解包会触发崩溃。修改为可选绑定判断:
// 替换原重复获取上下文的逻辑 guard let contextBefore = proxy.documentContextBeforeInput else { return // 无前置内容时直接返回,终止后续逻辑 } let last3Letter = contextBefore.suffix(3) let last2Letter = contextBefore.suffix(2) let lastLetter = contextBefore.suffix(1)
2. 修复按钮标题的强制解包
sender.titleLabel?.text可能为空,直接用!解包会崩溃,改为可选绑定:
// 替换原insertText逻辑 guard let character = sender.titleLabel?.text else { return } proxy.insertText(character)
3. 修正变量赋值顺序
原代码先调用replaceletters()再给bianyuanyin、bufferletters赋值,导致方法内变量未初始化,触发崩溃或功能失效。调整顺序为先赋值再调用方法:
// 原逻辑顺序错误,修改后: if lastLetter.contains("ɑ") { deleteletters = 1 bianyuanyin = "ɑ" bufferletters = lastLetter replaceletters() } if last2Letter == "UN" { deleteletters = 2 bianyuanyin = "U" bufferletters = last2Letter replaceletters() }
二、功能失效原因及修复
1. 优化变量声明
类中隐式可选变量建议改为普通可选类型,避免未初始化导致的异常:
var yuanyin: String? // 改用小驼峰命名,符合Swift规范 var bianyuanyin: String? var bufferletters: Substring? var deleteletters = 0 // 初始化deleteletters,避免未定义异常
2. 重构replaceletters()方法
避免直接操作titleLabel?.text,先处理字符串再调用setTitle,同时增加变量非空判断:
func replaceletters() { guard let targetYuanYin = bianyuanyin, let buffer = bufferletters else { return // 变量未初始化时直接返回 } let tone1 = targetYuanYin + "\u{0304}" let tone2 = targetYuanYin + "\u{0301}" let tone3 = targetYuanYin + "\u{030C}" let tone4 = targetYuanYin + "\u{0300}" Tone1Button.setTitle(buffer.replacingOccurrences(of: targetYuanYin, with: tone1), for: .normal) Tone2Button.setTitle(buffer.replacingOccurrences(of: targetYuanYin, with: tone2), for: .normal) Tone3Button.setTitle(buffer.replacingOccurrences(of: targetYuanYin, with: tone3), for: .normal) Tone4Button.setTitle(buffer.replacingOccurrences(of: targetYuanYin, with: tone4), for: .normal) }
3. 简化匹配逻辑
原正则表达式匹配无需.regularExpression选项,直接用contains()或==更高效:
// 替换原range(of:options:)判断 if lastLetter.contains("ɑ") { ... } if last2Letter == "UN" { ... }
三、修复后关键代码片段
class KeyboardViewController: UIInputViewController { var yuanyin: String? var bianyuanyin: String? var bufferletters: Substring? var deleteletters = 0 var shiftStatus = 0 // 需根据实际逻辑初始化 private var proxy: UITextDocumentProxy { return textDocumentProxy } @IBAction func keypressed(sender: UIButton) { guard let character = sender.titleLabel?.text else { return } proxy.insertText(character) if shiftStatus == 1 { shiftbuttonpressed(ShiftButton) } guard let contextBefore = proxy.documentContextBeforeInput else { return } let last3Letter = contextBefore.suffix(3) let last2Letter = contextBefore.suffix(2) let lastLetter = contextBefore.suffix(1) if lastLetter.contains("ɑ") { deleteletters = 1 bianyuanyin = "ɑ" bufferletters = lastLetter replaceletters() } if last2Letter == "UN" { deleteletters = 2 bianyuanyin = "U" bufferletters = last2Letter replaceletters() } } func replaceletters() { guard let targetYuanYin = bianyuanyin, let buffer = bufferletters else { return } let tone1 = targetYuanYin + "\u{0304}" let tone2 = targetYuanYin + "\u{0301}" let tone3 = targetYuanYin + "\u{030C}" let tone4 = targetYuanYin + "\u{0300}" Tone1Button.setTitle(buffer.replacingOccurrences(of: targetYuanYin, with: tone1), for: .normal) Tone2Button.setTitle(buffer.replacingOccurrences(of: targetYuanYin, with: tone2), for: .normal) Tone3Button.setTitle(buffer.replacingOccurrences(of: targetYuanYin, with: tone3), for: .normal) Tone4Button.setTitle(buffer.replacingOccurrences(of: targetYuanYin, with: tone4), for: .normal) } // 假设shiftbuttonpressed方法已实现 func shiftbuttonpressed(_ button: UIButton) { shiftStatus = 0 // 其他shift逻辑 } }
内容的提问来源于stack exchange,提问作者dennis li
相关产品推荐
相关产品推荐

