You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:00:47