如何将通用自定义对象保存到 UserDefaults?

2024-05-07

这是我的通用类:

open class SMState<T: Hashable>: NSObject, NSCoding {
    open var value: T

    open var didEnter: ( (_ state: SMState<T>) -> Void)?
    open var didExit:  ( (_ state: SMState<T>) -> Void)?

    public init(_ value: T) {
        self.value = value
    }

    convenience required public init(coder decoder: NSCoder) {
        let value = decoder.decodeObject(forKey: "value") as! T

        self.init(value)
    }

    public func encode(with aCoder: NSCoder) {
        aCoder.encode(value, forKey: "value")
    }
}

然后我想这样做:

    let stateEncodeData = NSKeyedArchiver.archivedData(withRootObject: currentState)
    UserDefaults.standard.set(stateEncodeData, forKey: "state")

就我而言currentState属于类型SMState<SomeEnum>.

但当我打电话时NSKeyedArchiver.archivedData,Xcode (9 beta 5) 显示一条紫色消息:

Attempting to archive generic Swift class 'StepUp.SMState<StepUp.RoutineViewController.RoutineState>' with mangled runtime name '_TtGC6StepUp7SMStateOCS_21RoutineViewController12RoutineState_'. Runtime names for generic classes are unstable and may change in the future, leading to non-decodable data.

我不太确定它想说什么。无法保存通用对象吗?

还有其他方法可以保存通用自定义对象吗?

edit:

即使我使用AnyHashable而不是泛型,我在调用时在运行时遇到相同的错误NSKeyedArchiver.archivedData:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: : unrecognized selector sent to instance

如果你想让泛型类采用NSCoding和泛型类型T然后将被编码和解码T 必须是符合属性列表的类型之一.

符合属性列表的类型有NSString, NSNumber, NSDate and NSData


一个可能的解决方案是创建一个协议PropertyListable并将属性列表兼容类型的所有 Swift 等效项扩展到该协议

协议要求是

  • An associated type.
  • 计算属性propertyListRepresentation将值转换为符合属性列表的类型。
  • 初始化器init(propertyList做相反的事情。

public protocol PropertyListable {
    associatedtype PropertyListType
    var propertyListRepresentation : PropertyListType { get }
    init(propertyList : PropertyListType)
}

以下是示例性实现String and Int.

extension String : PropertyListable {
    public typealias PropertyListType = String
    public var propertyListRepresentation : PropertyListType { return self }
    public init(propertyList: PropertyListType) { self.init(stringLiteral: propertyList) }
}

extension Int : PropertyListable {
    public typealias PropertyListType = Int
    public var propertyListRepresentation : PropertyListType { return self }
    public init(propertyList: PropertyListType) { self.init(propertyList) }
}

让我们声明一个示例枚举并采用PropertyListable

enum Foo : Int, PropertyListable {
    public typealias PropertyListType = Int

    case north, east, south, west

    public var propertyListRepresentation : PropertyListType { return self.rawValue }
    public init(propertyList: PropertyListType) {
        self.init(rawValue:  propertyList)!
    }
}

最后将您的泛型类替换为

open class SMState<T: PropertyListable>: NSObject, NSCoding {
    open var value: T

    open var didEnter: ( (_ state: SMState<T>) -> Void)?
    open var didExit:  ( (_ state: SMState<T>) -> Void)?

    public init(_ value: T) {
        self.value = value
    }

    convenience required public init(coder decoder: NSCoder) {
        let value = decoder.decodeObject(forKey: "value") as! T.PropertyListType
        self.init(T(propertyList: value))
    }

    public func encode(with aCoder: NSCoder) {
        aCoder.encode(value.propertyListRepresentation, forKey: "value")
    }
}

通过此实现,您可以创建一个实例并将其存档

let currentState = SMState<Foo>(Foo.north)
let stateEncodeData = NSKeyedArchiver.archivedData(withRootObject: currentState)

并再次取消存档

let restoredState = NSKeyedUnarchiver.unarchiveObject(with: stateEncodeData) as! SMState<Foo>
print(restoredState.value)

整个解决方案似乎很麻烦,但你必须满足以下限制:NSCoding需要符合属性列表的类型。如果您不需要像这样的自定义类型enum实施更加容易(而且更短)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将通用自定义对象保存到 UserDefaults? 的相关文章

  • 在现有 iOS 应用程序中集成 React-native(0.40.0) 后找不到 Yoga/Yoga.h 头文件

    在我的 Swift iOS 应用程序中集成 React Native 后 我无法构建 yoga Yoga h file cannot be found 我已经浏览了文档 查看了react native github页面 检查了类似问题的SO
  • 为什么我的视图仍然以横向呈现?

    我的视图是由导航控制器控制的 因此我将导航控制器支持的方向设置为明确的纵向和纵向UpSideDown 这可以工作 但是如果调用视图时前一个视图处于横向状态 它将以横向方式呈现并保持横向状态 直到设备旋转 如何防止这种情况发生 这是我的代码
  • init 中的 Swift 通用约束

    我有通用的 我希望能够用特定的约束来初始化它 约束仅用于初始化 班里的其他人并不关心 这是一个简化的示例 struct Generic
  • iOS 13 beta 外部屏幕上的 OverscanCompensation

    我正在测试一个应用程序的测试版 但遇到了外部屏幕的问题 我们看到应用程序周围有黑色边框 我们之前可以通过设置来纠正它overscanCompensation to none但在 iOS 13 中 该设置根本没有任何效果 我们曾经看到一个错误
  • 我可以/如何用 RC3 替换我的 KVO 东西?

    我正在尝试将一个使用 Facebook 的 KVOController 的 objc 应用程序移植到 Swift 我被鼓励去看看RC3 https github com ReactiveCocoa ReactiveCocoa作为一种替代且更
  • 仅将 UIImage 移动到另一个 UIImage 内部

    I have an UIImage which is shown in an UIImageView I also have another image in an UIImageView which lays above the firs
  • IOS7 状态栏在选定控制器上隐藏/显示

    我想在某些控制器上显示和隐藏状态栏 这可以完成吗 或者它更像是一个整体应用程序设置 我看过很多关于 plist 更新的帖子 问题 View controller based status bar appearance NO 如果这完成了 那
  • 使用 Simulator 时 Xcode 10 中的屏幕截图尺寸错误

    我正在尝试使用 Xcode 10 模拟器为 iTunes 制作屏幕截图 但图像大小错误 我读过Debug gt Optimize Rendering for Window Scale会有帮助 但在 Xcode 中没有这样的选项 有人有这个问
  • 检索 iPhone 中的 Outlook 联系人

    我想通过应用程序导入所有 Outlook 联系人 有什么办法可以做到这一点吗 请告诉我 您可以通过实施 Microsoft Exchange 服务器协议来实现此目的 微软MSDN http msdn microsoft com en us
  • 径向渐变绘制性能 - OpenGL-ES 可以改进吗?

    我正在开发一个图像处理应用程序 它将径向渐变叠加在从照片库加载的图像上 在屏幕上 我有一个滑块可以动态地增大 减小径向渐变的半径 我发现模拟器上的性能很好 但在 iPhone 3G 或 3GS 上就很糟糕了much移动滑块时重绘速度较慢 我
  • 具有自动布局的 UITableViewCell 中的 UILabel 高度错误

    我有一个UITableView单元格的固定高度为 100 点 这些单元格是在 xib 文件中创建的 该文件使用 3 个约束来固定UILabel到单元格的左 右和上边缘contentView 标签的垂直拥抱优先级设置为 1000 因为我希望单
  • 如何在 Xcode 4 中在 .h 和 .m 之间切换

    刚刚安装的 Xcode 4 到目前为止一切顺利 除了 Apple 更改了所有键盘快捷键 有人知道如何在 h 和 m 之间切换吗 苹果改变了各种快捷键 但要在标头和实现之间切换 新的快捷键是 You can change it back to
  • 两者都实现了类。将使用两者之一

    我有一个项目 它具有使用 SocketRocket 的依赖项 通过 CocoaPods 安装 并从 HeapAnalytics 导入了静态库 显然 HeapAnalytics 库已经使用了 SocketRocket 编译时没有出现错误 但在
  • 如何在 ios 7 上更改重新排序控制图像

    我正在寻找一种更改重新排序控件图像和大小的方法 我使用此代码来更改重新排序图像 void tableView UITableView tableView willDisplayCell UITableViewCell cell forRow
  • 如何自动缩放mapView以显示叠加层

    我可以在 mapView 上绘制多边形 但是我需要找到多边形并手动缩放它 有没有办法自动执行此过程 例如调整中心多边形 我浏览过互联网并阅读了一些相关文章 其中大多数都是基于折线和点的 任何形式的帮助将不胜感激 因为我正在寻找解决方案一段时
  • ViewWillAppear 没有被 UISplitViewController 调用

    背景和目标 我有一个基于 UISplitViewController 的 iPad 应用程序 到目前为止它支持 4 个方向 但现在我想将其锁定为仅横向 我变了shouldAutorotateToInterfaceOrientation左视图
  • 如何防止 RealmSwift 列表中出现重复项?

    如何防止向列表中添加重复项RealmSwift 我有我的User作为领域对象 但真正的数据源是服务器 只是使用领域在本地缓存用户 当我从服务器获取当前用户数据时 我想确保存储在领域中的用户拥有来自服务器的所有播放列表 以及它们的曲目列表等
  • 尝试复制文件时出错

    我正在尝试使用 NSFileManager 将临时文件复制到另一个位置 但是它失败并抱怨其中一个文件不存在 Copy temp file NSError error BOOL exists fileManager fileExistsAtP
  • Swift 使用哪种通用排序算法?它在排序数据上表现不佳

    我一直在挑选和探索 Swift 标准库sort 其函数为Array类型 令我惊讶的是 我注意到它在已经排序的数据上表现不佳 对数组进行排序Int打乱顺序似乎比对已经排序的同一个数组进行排序快 5 倍 对已打乱顺序的对象数组进行排序比对已按排
  • 将带有地理位置数据的照片保存到照片库 Swift 3

    如何使用地理位置元数据将照片保存到照片库 我已请求 并允许 应用程序访问用户位置 private func allowAccessToUserLocation locationManager CLLocationManager locati

随机推荐

  • android-button 背景可绘制不起作用

    这是我的 xml 可绘制代码 名称为 bts theme xml
  • Android:如何在触摸事件中手动实现长按?

    简短版本 我想要一种方法来在 onTouchEvent 上启动基于时间的计数器 并测试在响应之前是否已经过了一定的时间 作为手动 LongTouch 检测 解释 我有一个自定义 imageView 可以通过两根手指滑动滑入 滑出屏幕 我想向
  • Angular 2 测试 - 获取 DOM 元素样式

    我想在 Angular 2 应用程序中测试隐藏显示按钮的功能 测试是用 Jasmine 编写的 所以我需要检查display相关元素的属性 我怎样才能使用 Angular 获得这个属性debugElement 测试代码 let input
  • 我不应该在 Spring Boot 项目中使用“new”关键字吗?

    我正在研究 Spring Boot Rest API 最后我确实使用了new关键字在这里和那里 我想知道 当我在程序中使用 new 关键字时 我是否做错了什么 而如果在实际项目中绝对禁止使用new关键字 如果答案是肯定的 我应该注释我编写的
  • C# 中多个类的别名

    我想 正在努力 使我的代码更具可读性 我一直在使用以下类别名 using Histogram EmpiricScore
  • 加载包时 R 会话中止

    我的 RStudio 0 99 879 R 3 2 3 OSX 10 11 3 崩溃R Session Aborted每次运行都会出现错误提示require ggvis v0 4 2 我已经重新安装了 R RStudio 和 ggvis 没
  • 多个 Rails 应用程序,单个 MySQL 数据库

    我打算为 site com api site com admin site com 分别创建多个 Rails 应用程序 所有应用程序都将从一个 MySQL 数据库访问相同的表 应用程序和数据库在同一服务器上运行 对于上述访问场景 Rails
  • 如何列出当前正在验证的拉取请求中更改的所有文件(在 VSTS 中)?

    我有一个 PR 验证版本 我想列出 PR 中更改的所有文件以及状态 源在每个构建上同步 因此 在合并 PR 更改之前 源位于修订版A 通常origin master 让我将 PR 合并提交指定为B 我当前的实现调用git diff tree
  • iPhone - SSL 连接

    学习通过 iPhone 连接 ssl Web 服务的最佳起点是什么 到目前为止 我通过 SOAP 等通过 http 进行了一些基本连接 但我没有使用 https 的经验 任何好的资源 教程 起始参考 use nsurl class 都值得赞
  • UIButton突出显示区域延伸到按钮之外

    当用户触摸 UIButton 时 应启动突出显示状态 当他将手指滑到按钮之外 仍然没有抬起手指 时 按钮突出显示应该停止 并且当他抬起手指时 不应触发按钮 这种行为正是 iOS 的工作原理 但我对仍然应用突出显示的有效区域感到有点惊讶 对于
  • AngularJS 服务位于单独的文件中

    我的 app js 包含 var app angular module myApp config routeProvider function routeProvider http 服务看起来像 app service MyService
  • Python 扩展方法

    好的 在 C 中我们有这样的东西 public static string Destroy this string s return 所以基本上 当你有一个字符串时 你可以这样做 str This is my string to be de
  • Dagger 2:如何从 FragmentFactory 的子组件绑定父组件中的 Fragment Map

    我有这个 Dagger 2 配置 应用程序组件 kt Singleton Component modules AndroidSupportInjectionModule class AppModule class ActivityBindi
  • 枕头成像导入错误

    我通过 pip 将 Pillow 3 0 0 安装到 32 位 Windows 7 PC 上的 Python3 5 上 从 PIL 导入图像 给我 File C Python 3 5 lib site packages PIL Image
  • 当我打开在 Xcode 4 中创建的 Google 地图项目时,Xcode 5 会警告我的架构设置

    我刚刚更新到新发布的 Xcode 5 我正在开发一个使用 Google 地图 iOS SDK 的 iOS 应用程序 当我在 Xcode 4 中开发时 我改变了我的Architectures在我的项目设置中进行设置 按照 Google 的步骤
  • 将 Google 工作表图表导出为图像

    请您帮助了解如何使用谷歌脚本将图表导出到图像 我写了这段代码 但它不起作用 我担心 APIgetAs已弃用 function TestEmailCharts var sheet SpreadsheetApp getActiveSheet v
  • 无法将 Laravel 应用程序部署到 EC2

    我的 Laravel 项目全部在我的本地主机上运行 我将其部署到 EC2 但没有任何反应 我在开发控制台中看到的只是内部错误 500 我缺少什么 在部署到 AWS 之前我需要更改哪些内容 这是网址 http ec2 52 88 99 75
  • 构建一个“简单”的 php url 代理

    我需要在我正在构建的 Web 应用程序中实现一个简单的 PHP 代理 它基于 Flash 并且目标服务提供商不允许编辑其 crossdomain xml 文件 任何 php 专家都可以就以下 2 个选项提供建议吗 另外 我认为 但不确定 我
  • 重命名 PDF 文件中的指定目标

    我一直在 PDF 文件中使用命名目标来在文件中的特定位置打开 PDF 文件 负责生成 PDF 文档的团队使用工具从书签自动生成命名目的地 因此命名目的地往往具有诸如 9 Glossary 或 Additional Information 之
  • 如何将通用自定义对象保存到 UserDefaults?

    这是我的通用类 open class SMState