- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
为了让我的类(class)与 NSUserDefaults 兼容,我当前的类(class)有大约 50 行代码和解码变量。有更好的方法来处理这个问题吗?
示例:
init(coder aDecoder: NSCoder!) {
lightEnabled = aDecoder.decodeBoolForKey("lightEnabled")
soundEnabled = aDecoder.decodeBoolForKey("soundEnabled")
vibrateEnabled = aDecoder.decodeBoolForKey("vibrateEnabled")
pulseEnabled = aDecoder.decodeBoolForKey("pulseEnabled")
songs = aDecoder.decodeObjectForKey("songs") as! [Song]
currentSong = aDecoder.decodeIntegerForKey("currentSong")
enableBackgroundSound = aDecoder.decodeBoolForKey("enableBackgroundSound")
mixSound = aDecoder.decodeBoolForKey("mixSound")
playSoundInBackground = aDecoder.decodeBoolForKey("playSoundInBackground")
duckSounds = aDecoder.decodeBoolForKey("duckSounds")
BPMBackground = NSKeyedUnarchiver.unarchiveObjectWithData(aDecoder.decodeObjectForKey("BPMBackgorund") as! NSData) as! UIColor!
BPMPulseColor = NSKeyedUnarchiver.unarchiveObjectWithData(aDecoder.decodeObjectForKey("BPMPulseColor") as! NSData) as! UIColor!
TempoBackGround = NSKeyedUnarchiver.unarchiveObjectWithData(aDecoder.decodeObjectForKey("TempoBackGround") as! NSData) as! UIColor!
TempoPulseColor = NSKeyedUnarchiver.unarchiveObjectWithData(aDecoder.decodeObjectForKey("TempoPulseColor") as! NSData) as! UIColor!
TimeBackGround = NSKeyedUnarchiver.unarchiveObjectWithData(aDecoder.decodeObjectForKey("TimeBackGround") as! NSData) as! UIColor!
TimeStrokeColor = NSKeyedUnarchiver.unarchiveObjectWithData(aDecoder.decodeObjectForKey("TimeStrokeColor") as! NSData) as! UIColor!
TextColor = NSKeyedUnarchiver.unarchiveObjectWithData(aDecoder.decodeObjectForKey("TextColor") as! NSData) as! UIColor!
}
func encodeWithCoder(aCoder: NSCoder!) {
aCoder.encodeBool(lightEnabled, forKey: "lightEnabled")
aCoder.encodeBool(soundEnabled, forKey: "soundEnabled")
aCoder.encodeBool(vibrateEnabled, forKey: "vibrateEnabled")
aCoder.encodeBool(pulseEnabled, forKey: "pulseEnabled")
aCoder.encodeObject(songs, forKey: "songs")
aCoder.encodeInteger(currentSong, forKey: "currentSong")
aCoder.encodeBool(enableBackgroundSound, forKey: "enableBackgroundSound")
aCoder.encodeBool(mixSound, forKey: "mixSound")
aCoder.encodeBool(playSoundInBackground, forKey: "playSoundInBackground")
aCoder.encodeBool(duckSounds, forKey: "duckSounds")
aCoder.encodeObject(BPMBackground.archivedData(), forKey: "BPMBackground")
aCoder.encodeObject(BPMPulseColor.archivedData(), forKey: "BPMPulseColor")
aCoder.encodeObject(TempoBackGround.archivedData(), forKey: "TempoBackGround")
aCoder.encodeObject(TempoPulseColor.archivedData(), forKey: "TempoPulseColor")
aCoder.encodeObject(TimeBackGround.archivedData(), forKey: "TimeBackGround")
aCoder.encodeObject(TimeStrokeColor.archivedData(), forKey: "TimeStrokeColor")
aCoder.encodeObject(TextColor.archivedData(), forKey: "TextColor")
}
最佳答案
您应该创建一个结构或枚举来组织您的 key ,因为您的方式很容易出现拼写错误。把它放在你类(class)的正上方
enum Key: String {
case allSettings
case lightEnabled
case soundEnabled
}
不仅仅是像这样调用键
...forKey: Key.lightEnabled.rawValue)
关于您的问题,我在尝试保存 40 个关卡的属性(最佳时间、关卡解锁状态等)时遇到了同样的问题。我最初做了你尝试过的事情,这简直是疯狂。
我最终为我的数据使用了数组/字典甚至字典数组,这将我的代码减少了大约 80%。
还有一个好处是,如果您需要保存 LevelUnlock bools 之类的东西,它会让您以后的生活变得更加轻松。在我的例子中,我有一个 UnlockAllLevels 按钮,现在我可以在我的字典/数组中循环,并在几行代码中更新/检查 levelUnlock bools。比使用大量 if-else 或 switch 语句来单独检查每个属性要好得多。
例如
var settingsDict = [
Key.lightEnabled.rawValue: false,
Key.soundEnabled.rawValue: false,
...
]
比在解码器方法中你这样说
注意:这种方式将考虑到您可能会向 SettingsDict 添加新值,并且在下一次应用启动时不会删除这些值,因为您没有用保存的字典替换整个字典,您只更新已经存在的值。
// If no saved data found do nothing
if var savedSettingsDict = decoder.decodeObjectForKey(Key.allSettings.rawValue) as? [String: Bool] {
// Update the dictionary values with the previously saved values
savedSettingsDict.forEach {
// If the key does not exist anymore remove it from saved data.
guard settingsDict.keys.contains($0) else {
savedSettingsDict.removeValue(forKey: $0)
return
}
settingsDict[$0] = $1
}
}
如果你使用多个词典,那么你的解码器方法将再次变得困惑,你也会重复很多代码。为避免这种情况,您可以使用泛型创建 NSCoder 的扩展。
extension NSCoder {
func decodeObject<T>(_ object: [String: T], forKey key: String) -> [String: T] {
guard var savedData = decodeObject(forKey: key) as? [String: T] else { return object }
var newData = object
savedData.forEach {
guard object.keys.contains($0) else {
savedData[$0] = nil
return
}
newData[$0] = $1
}
return newData
}
}
然后你可以在每个字典的解码器方法中写这个。
settingsDict = aDecoder.decodeObject(settingsDict, forKey: Key.allSettings.rawValue)
您的编码器方法如下所示。
encoder.encodeObject(settingsDict, forKey: Key.allSettings.rawValue)
在您的游戏/应用中,您可以像这样使用它们
settingsDict[Key.lightEnabled.rawValue] = true
if settingsDict[Key.lightEnabled.rawValue] == true {
/// light is turned on, do something
}
这种方式也使得集成 iCloud KeyValue 存储变得非常容易(只需创建一个 iCloud 字典),同样主要是因为它非常容易保存和比较大量的值,只需很少的代码。
更新:
为了更轻松地调用它们,我喜欢在 GameData 类中创建一些方便的 getter/setter。这样做的好处是您可以更轻松地在项目中调用这些属性(就像您的旧方法一样),但您的编码/解码方法仍将保持紧凑。您还可以执行诸如循环比较值之类的操作。
var isLightEnabled: Bool {
get { return settingsDict[Key.lightEnabled.rawValue] ?? false }
set { settingsDict[Key.lightEnabled.rawValue] = newValue }
}
var isSoundEnabled: Bool {
get { return settingsDict[Key.soundEnabled.rawValue] ?? false }
set { settingsDict[Key.soundEnabled.rawValue] = newValue }
}
而且您可以像普通属性一样调用它们。
isLightEnabled = true
if isLightEnabled {
/// light is turned on, do something
}
关于ios - 有没有比使用 NSCoder 编码和解码所有内容更好的方法将自定义类保存到 NSUserDefaults?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35821732/
我尝试根据表单元素的更改禁用/启用保存按钮。但是,当通过弹出按钮选择更改隐藏输入字段值时,保存按钮不受影响。 下面是我的代码。我正在尝试序列化旧的表单值并与更改后的表单值进行比较。但我猜隐藏的字段值无
我正在尝试保存模型的实例,但我得到了 Invalid EmbeddedDocumentField item (1) 其中 1 是项目的 ID(我认为)。 模型定义为 class Graph(Docum
我有一个非常奇怪的问题......在我的 iPhone 应用程序中,用户可以打开相机胶卷中的图像,在我的示例中 1920 x 1080 像素 (72 dpi) 的壁纸。 现在,想要将图像的宽度调整为例
目前,我正在使用具有排序/过滤功能的数据表成功地从我的数据库中显示图像元数据。在我的数据表下方,我使用第三方图像覆盖流( http://www.jacksasylum.eu/ContentFlow/
我的脚本有问题。我想按此顺序执行以下步骤: 1. 保存输入字段中的文本。 2. 删除输入字段中的所有文本。 3. 在输入字段中重新加载之前删除的相同文本。 我的脚本的问题是 ug()- 函数在我的文本
任何人都可以帮助我如何保存多对多关系吗?我有任务,用户可以有很多任务,任务可以有很多用户(多对多),我想要实现的是,在更新表单中,管理员可以将多个用户分配给特定任务。这是通过 html 多选输入来完成
我在 Tensorflow 中训练了一个具有批归一化的模型。我想保存模型并恢复它以供进一步使用。批量归一化是通过 完成的 def batch_norm(input, phase): retur
我遇到了 grails 的问题。我有一个看起来像这样的域: class Book { static belongsTo = Author String toString() { tit
所以我正在开发一个应用程序,一旦用户连接(通过 soundcloud),就会出现以下对象: {userid: userid, username: username, genre: genre, fol
我正在开发一个具有多选项卡布局的 Angular 7 应用程序。每个选项卡都包含一个组件,该组件可以引用其他嵌套组件。 当用户选择一个新的/另一个选项卡时,当前选项卡上显示的组件将被销毁(我不仅仅是隐
我尝试使用 JEditorPane 进行一些简单的文本格式化,但随着知识的增长,我发现 JTextPane 更容易实现并且更强大。 我的问题是如何将 JTextPane 中的格式化文本保存到文件?它应
使用 Docker 相当新。 我为 Oracle 11g Full 提取了一个图像。创建了一个数据库并将应用程序安装到容器中。 正确配置后,我提交了生成 15GB 镜像的容器。 测试了该图像的新容器,
我是使用 Xcode 和 swift 的新手,仍在学习中。我在将核心数据从实体传递到文本字段/标签时遇到问题,然后用户可以选择编辑和保存记录。我的目标是,当用户从 friendslistViewCon
我正在用 Java 编写 Android 游戏,我需要一种可靠的方法来快速保存和加载应用程序状态。这个问题似乎适用于大多数 OO 语言。 了解我需要保存的内容:我正在使用策略模式来控制我的游戏实体。我
我想知道使用 fstream 加载/保存某种结构类型的数组是否是个好主意。注意,我说的是加载/保存到二进制文件。我应该加载/保存独立变量,例如 int、float、boolean 而不是结构吗?我这么
我希望能够将 QNetworkReply 保存到 QString/QByteArray。在我看到的示例中,它们总是将流保存到另一个文件。 目前我的代码看起来像这样,我从主机那里得到一个字符串,我想做的
我正在创建一个绘图应用程序。我有一个带有 Canvas 的自定义 View ,它根据用户输入绘制线条: class Line { float startX, startY, stopX, stop
我有 3 个 Activity 第一个 Activity 调用第二个 Activity ,第二个 Activity 调用第三个 Activity 。 第二个 Activity 使用第一个 Activi
我想知道如何在 Xcode 中保存 cookie。我想使用从一个网页获取的 cookie 并使用它访问另一个网页。我使用下面的代码登录该网站,我想保存从该连接获得的 cookie,以便在我建立另一个连
我有一个 SQLite 数据库存储我的所有日历事件,建模如下: TimerEvent *Attributes -date -dateForMark -reminder *Relat
我是一名优秀的程序员,十分优秀!