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

如何修复“该解码器仅能解码遵循NSSecureCoding协议的类,类‘UIImageView’未遵循该协议”错误?

解决UIImageView归档/解档的NSSecureCoding错误

你遇到的错误核心原因很明确:UIImageView(包括它的父类UIView)并没有遵循NSSecureCoding协议,而你使用的NSKeyedUnarchiver.unarchivedObject(ofClass:from:)方法会强制要求被解档的类必须支持安全编码,所以直接解档整个UIImageView实例会触发这个报错。

下面给你两种可行的解决方案,优先推荐第二种更稳妥的实现方式:

方案一:使用非安全解档方法(仅临时兼容,不推荐)

如果你只是需要快速绕过这个问题,可以使用苹果已经标记为废弃的unarchiveObject(with:)方法,它不会强制要求安全编码:

do {
    if let imageView = NSKeyedUnarchiver.unarchiveObject(with: data!) as? UIImageView {
        self.backgroundIV = imageView
        print("Un Archived...")
    }
} catch {
    print(error)
}

⚠️ 注意:这个方法在iOS 12及以上版本被废弃,存在安全风险(可能被恶意利用注入非法数据),仅建议用于旧项目临时兼容,不推荐在新代码中使用。

方案二:归档视图关键属性(推荐最佳实践)

直接归档整个UIView或其子类从来都不是最优选择——视图包含大量内部状态、层级结构和非归档友好的属性,容易出现解档失败、状态不一致等问题。更好的方式是提取你需要保留的核心属性,归档这些属性,解档时重新创建视图并赋值:

归档代码:

// 提取UIImageView的核心属性(按需添加更多,比如layer的圆角、边框等)
guard let image = self.backgroundIV?.image,
      let frame = self.backgroundIV?.frame,
      let contentMode = self.backgroundIV?.contentMode else {
    return
}

// 用字典封装需要归档的属性
let viewProperties: [String: Any] = [
    "image": image,
    "frame": frame,
    "contentMode": contentMode.rawValue,
    "cornerRadius": self.backgroundIV?.layer.cornerRadius ?? 0,
    "borderWidth": self.backgroundIV?.layer.borderWidth ?? 0,
    "borderColor": self.backgroundIV?.layer.borderColor ?? UIColor.clear.cgColor
]

// 归档字典数据
let data = try? NSKeyedArchiver.archivedData(withRootObject: viewProperties, requiringSecureCoding: false)

解档代码:

do {
    guard let viewProperties = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data!) as? [String: Any],
          let image = viewProperties["image"] as? UIImage,
          let frame = viewProperties["frame"] as? CGRect,
          let contentModeRaw = viewProperties["contentMode"] as? Int,
          let contentMode = UIView.ContentMode(rawValue: contentModeRaw) else {
        return
    }
    
    // 重新创建UIImageView并赋值属性
    let imageView = UIImageView(frame: frame)
    imageView.image = image
    imageView.contentMode = contentMode
    // 还原layer相关属性
    imageView.layer.cornerRadius = viewProperties["cornerRadius"] as? CGFloat ?? 0
    imageView.layer.borderWidth = viewProperties["borderWidth"] as? CGFloat ?? 0
    imageView.layer.borderColor = viewProperties["borderColor"] as? CGColor
    
    self.backgroundIV = imageView
    print("Un Archived...")
} catch {
    print(error)
}

这种方式的优势很明显:

  • 规避了直接归档视图的安全和兼容性问题
  • 只保存你真正需要的状态,缩小归档数据体积
  • 解档后的视图状态完全可控,避免莫名的层级或渲染bug

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 10:32:47