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

iOS14.6下@objc枚举存入字典触发malloc分配崩溃问题求助

问题原因分析

这是iOS 14.6系统中Swift与Objective-C桥接的特定bug导致的:你定义的ConnectState是标记@objc的UInt8类型枚举,当把它的rawValue(UInt8类型)或枚举本身存入[String: Any]字典时,Swift在将UInt8桥接为Objective-C兼容的NSNumber时出现错误,错误地将极小的UInt8值解析成了超大的内存分配尺寸(日志里的1152921504606863360是典型的64位溢出后的值),最终触发malloc分配失败。

而直接将枚举作为userInfo参数传入NotificationCenter时,系统使用了更直接的Swift类型传递路径,绕过了有问题的桥接逻辑,因此未出现崩溃。

解决方法

以下方案按推荐程度排序:

方案1:将UInt8 rawValue转换为Int后存入字典

修改赋值代码,把connectState.rawValue转为Int类型,避免桥接时的类型错误:

func connectStateChange(_ connectState: ConnectState, _ serialNumber: String) {
     var userInfo: [String: Any] = [:]
     // 转换为Int后存入字典
     userInfo[ConstValue.connectState] = Int(connectState.rawValue)
     userInfo[ConstValue.serialNumber] = serialNumber
     NotificationCenter.default.post(name: Notification.Name(Global.HomeDeviceStateChange), object: nil, userInfo: userInfo)
}

接收通知时,再将Int转回UInt8初始化枚举:

// 通知接收代码示例
if let stateRawValue = userInfo[ConstValue.connectState] as? Int,
   let connectState = ConnectState(rawValue: UInt8(stateRawValue)) {
    // 使用connectState进行业务逻辑处理
}

方案2:修改枚举的原始值类型为UInt/Int

直接将枚举的原始值类型从UInt8改为UInt或Int,规避iOS14.6的桥接bug:

@objc enum ConnectState: UInt { // 也可使用Int类型
    case connected = 0x00
    case disConnected = 0x01
    // 保留原有的description实现
}

修改后原赋值代码无需改动,可直接存入字典:

// 存rawValue或枚举本身都可以
userInfo[ConstValue.connectState] = connectState.rawValue
// 或者 userInfo[ConstValue.connectState] = connectState

方案3:自定义包装结构体(备选方案)

如果不想修改枚举或rawValue类型,可以用简单结构体包装枚举,避免直接桥接UInt8:

struct ConnectStateWrapper {
    let state: ConnectState
}

存入字典时:

userInfo[ConstValue.connectState] = ConnectStateWrapper(state: connectState)

接收通知时取出包装器获取枚举值即可。


内容的提问来源于stack exchange,提问作者Avicii4ever

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:32:57