在我的 macOS 和 iOS 应用程序中,我使用从此处创建的颜色:https://uiwjs.github.io/ui-color/ 然后 f.e.效果很好。
Color(red: 1.47, green: 1.9, blue: 2.3).opacity(1)
但是,对于某些颜色,我希望将它们保存在 UserDefaults 中,并通过
UserDefaults.standard
方法读/写,并通过 @AppStorage
读/写。
我确实尝试使用,但这给了我运行时错误。
static let infoListRowReadBGColor = Color(red: 2.55, green: 1.71, blue: 1.07).opacity(1)
static let infoListRowUnReadBGColor = Color(red: 2.55, green: 2.12, blue: 1.38).opacity(1)
var defaults = UserDefaults.standard
defaults.setValue(InAppDefaults.infoListRowReadBGColor, forKey: "infoListRowReadBGColor")
defaults.setValue(InAppDefaults.infoListRowUnReadBGColor, forKey: "infoListRowUnReadBGColor")
我需要更改什么才能使用
UserDefaults.standard
和 @AppStorage
使其工作、读取和写入?我确实尝试了这里的帖子中的扩展方法,但我想我做了一些非常错误的事情,因为它不适用于@AppStorage
。
使用 Xcode 13 和 14 获取 macOS 12 和 iOS 15 的开发结果。
您可以尝试将颜色转换为数据并存储数据。
这里有一个扩展 UIColor 的 uikit 版本,你也可以将它用于 SwiftUI 的颜色
import UIKit
extension UIColor {
class func color(data: Data) -> UIColor {
try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as! UIColor
}
func encode() -> Data {
try! NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false)
}
}
您可以使用编码函数保留颜色,一旦检索到数据,您可以将其传递给类函数来获取颜色
默认情况下,您无法将 Color() 存储在 UserDefaults 中,但您可以使用 @AppStorage 和 NSKeyedArchiver 来实现此结果。 本文中提供了完整的示例和文档。
创建扩展:
import SwiftUI
import UIKit
extension Color: RawRepresentable {
public init?(rawValue: String) {
guard let data = Data(base64Encoded: rawValue) else {
self = .black
return
}
do {
if let color = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: data) {
self = Color(color)
} else {
self = .black
}
} catch {
self = .black
}
}
public var rawValue: String {
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: UIColor(self), requiringSecureCoding: false) as Data
return data.base64EncodedString()
} catch {
return ""
}
}
}
并这样使用它:
@AppStorage("colorkey") var storedColor: Color = .black
var body: some View {
VStack {
ColorPicker("Persisted Color Picker", selection: $storedColor, supportsOpacity: true)
}
}
EJZ给出的答案让我走上了正轨。我也尝试过其他方法,但 EJZ 方法只需稍加调整即可用于 iOS 和 OSX。不想编辑他的答案以保持清晰,我将他的部分和我的调整复制到这个答案中。
import Foundation
import SwiftUI
#if os(iOS)
import UIKit
#elseif os(OSX)
import AppKit
#endif
这是我根据操作系统差异调整的文件
extension Color: RawRepresentable {
public init?(rawValue: String) {
guard let data = Data(base64Encoded: rawValue) else {
self = .gray
return
}
do{
#if os(iOS)
let color = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? UIColor ?? .gray
#elseif os(OSX)
let color = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? NSColor ?? .gray
#endif
self = Color(color)
}catch{
self = .gray
}
}
public var rawValue: String {
do{
#if os(iOS)
let data = try NSKeyedArchiver.archivedData(withRootObject: UIColor(self), requiringSecureCoding: false) as Data
#elseif os(OSX)
let data = try NSKeyedArchiver.archivedData(withRootObject: NSColor(self), requiringSecureCoding: false) as Data
#endif
return data.base64EncodedString()
}catch{
return ""
}
}
}
两者都可以很好地与(使用 EJZ 代码)@AppStorage SwiftUI 视图和两个系统配合使用。
@AppStorage("key") var storedColor: Color = .gray
但是:为什么保存的原始数据大小这么大?