Add support for SwiftUI `Color` (#84)

Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
This commit is contained in:
hank121314 2021-10-16 20:01:16 +08:00 committed by GitHub
parent 8a6e4a96fd
commit 55f3302c3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 2 deletions

View File

@ -1,4 +1,5 @@
import Foundation import Foundation
import SwiftUI
#if os(macOS) #if os(macOS)
import AppKit import AppKit
#else #else
@ -296,6 +297,36 @@ extension Defaults {
} }
} }
extension Defaults {
@available(iOS 15.0, macOS 11.0, tvOS 15.0, watchOS 8.0, iOSApplicationExtension 15.0, macOSApplicationExtension 11.0, tvOSApplicationExtension 15.0, watchOSApplicationExtension 8.0, *)
public struct ColorBridge: Bridge {
public typealias Value = Color
public typealias Serializable = Data
#if os(macOS)
private typealias NativeColor = NSColor
#else
private typealias NativeColor = UIColor
#endif
public func serialize(_ value: Value?) -> Serializable? {
guard let value = value else {
return nil
}
return NativeColor.bridge.serialize(NativeColor(value))
}
public func deserialize(_ object: Serializable?) -> Value? {
guard let nativeColor = NativeColor.bridge.deserialize(object) else {
return nil
}
return Value(nativeColor)
}
}
}
extension Defaults { extension Defaults {
public struct AnyBridge: Defaults.Bridge { public struct AnyBridge: Defaults.Bridge {
public typealias Value = Defaults.AnySerializable public typealias Value = Defaults.AnySerializable

View File

@ -1,5 +1,6 @@
import Foundation import Foundation
import CoreGraphics import CoreGraphics
import SwiftUI
#if os(macOS) #if os(macOS)
import AppKit import AppKit
#else #else
@ -136,6 +137,12 @@ extension Dictionary: Defaults.Serializable where Key: LosslessStringConvertible
public static var bridge: Defaults.DictionaryBridge<Key, Value> { Defaults.DictionaryBridge() } public static var bridge: Defaults.DictionaryBridge<Key, Value> { Defaults.DictionaryBridge() }
} }
@available(iOS 15.0, macOS 11.0, tvOS 15.0, watchOS 8.0, iOSApplicationExtension 15.0, macOSApplicationExtension 11.0, tvOSApplicationExtension 15.0, watchOSApplicationExtension 8.0, *)
extension Color: Defaults.Serializable {
public static let bridge = Defaults.ColorBridge()
}
#if os(macOS) #if os(macOS)
/// `NSColor` conforms to `NSSecureCoding`, so it goes to `NSSecureCodingBridge`. /// `NSColor` conforms to `NSSecureCoding`, so it goes to `NSSecureCodingBridge`.
extension NSColor: Defaults.Serializable {} extension NSColor: Defaults.Serializable {}

View File

@ -3,25 +3,35 @@ import Foundation
import SwiftUI import SwiftUI
import Defaults import Defaults
#if os(macOS)
typealias NativeColor = NSColor
#else
typealias NativeColor = UIColor
#endif
@available(macOS 11.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
extension Defaults.Keys { extension Defaults.Keys {
fileprivate static let hasUnicorn = Key<Bool>("swiftui_hasUnicorn", default: false) fileprivate static let hasUnicorn = Key<Bool>("swiftui_hasUnicorn", default: false)
fileprivate static let user = Key<User>("swiftui_user", default: User(username: "Hank", password: "123456")) fileprivate static let user = Key<User>("swiftui_user", default: User(username: "Hank", password: "123456"))
fileprivate static let setInt = Key<Set<Int>>("swiftui_setInt", default: Set(1...3)) fileprivate static let setInt = Key<Set<Int>>("swiftui_setInt", default: Set(1...3))
fileprivate static let color = Key<Color>("swiftui_color", default: .black)
} }
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) @available(macOS 11.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
struct ContentView: View { struct ContentView: View {
@Default(.hasUnicorn) var hasUnicorn @Default(.hasUnicorn) var hasUnicorn
@Default(.user) var user @Default(.user) var user
@Default(.setInt) var setInt @Default(.setInt) var setInt
@Default(.color) var color
var body: some View { var body: some View {
Text("User \(user.username) has Unicorn: \(String(hasUnicorn))") Text("User \(user.username) has Unicorn: \(String(hasUnicorn))")
.foregroundColor(color)
Toggle("Toggle Unicorn", isOn: $hasUnicorn) Toggle("Toggle Unicorn", isOn: $hasUnicorn)
} }
} }
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) @available(macOS 11.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
final class DefaultsSwiftUITests: XCTestCase { final class DefaultsSwiftUITests: XCTestCase {
override func setUp() { override func setUp() {
super.setUp() super.setUp()
@ -38,13 +48,17 @@ final class DefaultsSwiftUITests: XCTestCase {
XCTAssertFalse(view.hasUnicorn) XCTAssertFalse(view.hasUnicorn)
XCTAssertEqual(view.user.username, "Hank") XCTAssertEqual(view.user.username, "Hank")
XCTAssertEqual(view.setInt.count, 3) XCTAssertEqual(view.setInt.count, 3)
XCTAssertEqual(NativeColor(view.color), NativeColor(Color.black))
view.user = User(username: "Chen", password: "123456") view.user = User(username: "Chen", password: "123456")
view.hasUnicorn.toggle() view.hasUnicorn.toggle()
view.setInt.insert(4) view.setInt.insert(4)
view.color = Color(.sRGB, red: 100, green: 100, blue: 100, opacity: 1)
XCTAssertTrue(view.hasUnicorn) XCTAssertTrue(view.hasUnicorn)
XCTAssertEqual(view.user.username, "Chen") XCTAssertEqual(view.user.username, "Chen")
XCTAssertEqual(view.setInt, Set(1...4)) XCTAssertEqual(view.setInt, Set(1...4))
XCTAssertFalse(Default(.hasUnicorn).defaultValue) XCTAssertFalse(Default(.hasUnicorn).defaultValue)
XCTAssertFalse(Default(.hasUnicorn).isDefaultValue) XCTAssertFalse(Default(.hasUnicorn).isDefaultValue)
XCTAssertNotEqual(NativeColor(view.color), NativeColor(Color.black))
XCTAssertEqual(NativeColor(view.color), NativeColor(Color(.sRGB, red: 100, green: 100, blue: 100, opacity: 1)))
} }
} }

View File

@ -79,6 +79,7 @@ Add `https://github.com/sindresorhus/Defaults` in the [“Swift Package Manager
- `URL` - `URL`
- `NSColor` (macOS) - `NSColor` (macOS)
- `UIColor` (iOS) - `UIColor` (iOS)
- `Color` (SwiftUI)
- `Codable` - `Codable`
- `NSSecureCoding` - `NSSecureCoding`