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

iOS 16下如何复制UIView?适配废弃API后遇编码报错

解决UIView复制时的NSSecureCoding错误(适配iOS 16)

问题背景

原本使用以下Swift代码实现UIView的复制功能:

extension UIView {
    func copyObject<T:NSObject>() throws -> T? {
        let data = try NSKeyedArchiver.archivedData(withRootObject:self, requiringSecureCoding:false)
        return try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? T
    }
}

适配iOS 16后,代码出现API废弃警告:

'unarchiveObject(with:)' was deprecated in iOS 12.0: Use +unarchivedObjectOfClass:fromData:error: instead

'archivedData(withRootObject:)' was deprecated in iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead

修改警告后的代码如下:

func copyView<T: UIView>() -> T {
    let data = try? NSKeyedArchiver.archivedData(withRootObject:self, requiringSecureCoding:false)
    return try! NSKeyedUnarchiver.unarchivedObject(ofClass: UIView.self, from:data!)  as! T
    //return NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: self)) as! T
}

执行复制操作时出现以下错误:

error: Error Domain=NSCocoaErrorDomain Code=4864 "This decoder will only decode classes that adopt NSSecureCoding. Class 'UIView' does not adopt it." UserInfo={NSDebugDescription=This decoder will only decode classes that adopt NSSecureCoding. Class 'UIView' does not adopt it.}


解决方案

问题核心是unarchivedObject(ofClass:from:)强制要求目标类遵循NSSecureCoding,但系统UIView并未实现该协议。改用兼容的解档方法并优化错误处理即可解决:

修正后的代码

extension UIView {
    func copyView<T: UIView>() throws -> T {
        // 归档数据,保持关闭安全编码要求
        let data = try NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false)
        // 使用不强制安全编码的解档方法
        guard let copiedView = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? T else {
            throw NSError(domain: "ViewCopyError", code: -1, userInfo: [NSLocalizedDescriptionKey: "视图复制失败"])
        }
        return copiedView
    }
}

关键说明

  • 保留unarchiveTopLevelObjectWithData(_:):该方法不强制验证NSSecureCoding,适配系统UIView的特性
  • 移除不安全的强制解包:用try替代try?、try!,通过guard做类型校验,配合自定义错误抛出提升代码健壮性
  • 明确泛型约束:将泛型约束限定为UIView,更贴合视图复制的场景

如果是自定义UIView子类需要支持安全编码,可手动遵循NSSecureCoding并实现init?(coder:)、encode(with:)方法,但系统UIView无需额外处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 15:42:17