Skip to content

Commit

Permalink
Add support for SwiftUI Color (#84)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <[email protected]>
  • Loading branch information
hank121314 and sindresorhus authored Oct 16, 2021
1 parent 8a6e4a9 commit 55f3302
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 2 deletions.
31 changes: 31 additions & 0 deletions Sources/Defaults/Defaults+Bridge.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
import SwiftUI
#if os(macOS)
import AppKit
#else
Expand Down Expand Up @@ -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 {
public struct AnyBridge: Defaults.Bridge {
public typealias Value = Defaults.AnySerializable
Expand Down
7 changes: 7 additions & 0 deletions Sources/Defaults/Defaults+Extensions.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation
import CoreGraphics
import SwiftUI
#if os(macOS)
import AppKit
#else
Expand Down Expand Up @@ -136,6 +137,12 @@ extension Dictionary: Defaults.Serializable where Key: LosslessStringConvertible
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)
/// `NSColor` conforms to `NSSecureCoding`, so it goes to `NSSecureCodingBridge`.
extension NSColor: Defaults.Serializable {}
Expand Down
18 changes: 16 additions & 2 deletions Tests/DefaultsTests/DefaultsSwiftUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,35 @@ import Foundation
import SwiftUI
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 {
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 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 {
@Default(.hasUnicorn) var hasUnicorn
@Default(.user) var user
@Default(.setInt) var setInt
@Default(.color) var color

var body: some View {
Text("User \(user.username) has Unicorn: \(String(hasUnicorn))")
.foregroundColor(color)
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 {
override func setUp() {
super.setUp()
Expand All @@ -38,13 +48,17 @@ final class DefaultsSwiftUITests: XCTestCase {
XCTAssertFalse(view.hasUnicorn)
XCTAssertEqual(view.user.username, "Hank")
XCTAssertEqual(view.setInt.count, 3)
XCTAssertEqual(NativeColor(view.color), NativeColor(Color.black))
view.user = User(username: "Chen", password: "123456")
view.hasUnicorn.toggle()
view.setInt.insert(4)
view.color = Color(.sRGB, red: 100, green: 100, blue: 100, opacity: 1)
XCTAssertTrue(view.hasUnicorn)
XCTAssertEqual(view.user.username, "Chen")
XCTAssertEqual(view.setInt, Set(1...4))
XCTAssertFalse(Default(.hasUnicorn).defaultValue)
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)))
}
}
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Add `https://github.com/sindresorhus/Defaults` in the [“Swift Package Manager
- `URL`
- `NSColor` (macOS)
- `UIColor` (iOS)
- `Color` (SwiftUI)
- `Codable`
- `NSSecureCoding`

Expand Down

0 comments on commit 55f3302

Please sign in to comment.