From 04f9b3f45ea33cc54e228debe12a98635fd3515e Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 11 Sep 2021 10:49:06 +0700 Subject: [PATCH] Support types that conform to both `Codable` and `NSSecureCoding` (#80) --- Sources/Defaults/Defaults+Bridge.swift | 7 +++++++ Sources/Defaults/Defaults+Extensions.swift | 4 ++++ Tests/DefaultsTests/DefaultsCodableTests.swift | 18 ++++++++++++++++++ readme.md | 3 +++ 4 files changed, 32 insertions(+) diff --git a/Sources/Defaults/Defaults+Bridge.swift b/Sources/Defaults/Defaults+Bridge.swift index c440f6e..fbc1277 100644 --- a/Sources/Defaults/Defaults+Bridge.swift +++ b/Sources/Defaults/Defaults+Bridge.swift @@ -46,6 +46,13 @@ extension Defaults { public struct RawRepresentableCodableBridge: CodableBridge {} } +/** +This exists to avoid compiler ambiguity. +*/ +extension Defaults { + public struct CodableNSSecureCodingBridge: CodableBridge {} +} + extension Defaults { public struct URLBridge: CodableBridge { public typealias Value = URL diff --git a/Sources/Defaults/Defaults+Extensions.swift b/Sources/Defaults/Defaults+Extensions.swift index 90fd54c..0e616d6 100644 --- a/Sources/Defaults/Defaults+Extensions.swift +++ b/Sources/Defaults/Defaults+Extensions.swift @@ -86,6 +86,10 @@ extension Defaults.Serializable where Self: Codable { public static var bridge: Defaults.TopLevelCodableBridge { Defaults.TopLevelCodableBridge() } } +extension Defaults.Serializable where Self: Codable & NSSecureCoding { + public static var bridge: Defaults.CodableNSSecureCodingBridge { Defaults.CodableNSSecureCodingBridge() } +} + extension Defaults.Serializable where Self: RawRepresentable { public static var bridge: Defaults.RawRepresentableBridge { Defaults.RawRepresentableBridge() } } diff --git a/Tests/DefaultsTests/DefaultsCodableTests.swift b/Tests/DefaultsTests/DefaultsCodableTests.swift index cd98bb6..c6f1ecb 100644 --- a/Tests/DefaultsTests/DefaultsCodableTests.swift +++ b/Tests/DefaultsTests/DefaultsCodableTests.swift @@ -8,6 +8,19 @@ private struct Unicorn: Codable, Defaults.Serializable { private let fixtureCodable = Unicorn(isUnicorn: true) +@objc(UnicornCodableAndNSSecureCoding) +private final class UnicornCodableAndNSSecureCoding: NSObject, NSSecureCoding, Codable, Defaults.Serializable { + static let supportsSecureCoding = true + + func encode(with coder: NSCoder) {} + + init?(coder: NSCoder) {} + + override init() { + super.init() + } +} + extension Defaults.Keys { fileprivate static let codable = Key("codable", default: fixtureCodable) fileprivate static let codableArray = Key<[Unicorn]>("codable", default: [fixtureCodable]) @@ -120,6 +133,11 @@ final class DefaultsCodableTests: XCTestCase { XCTAssertFalse(Defaults[.codableDictionary]["0"]?.isUnicorn ?? true) } + func testCodableAndNSSecureCoding() { + let fixture = UnicornCodableAndNSSecureCoding() + _ = Defaults.Key("testCodableAndNSSecureCoding", default: fixture) + } + @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, iOSApplicationExtension 13.0, macOSApplicationExtension 10.15, tvOSApplicationExtension 13.0, watchOSApplicationExtension 6.0, *) func testObserveKeyCombine() { let key = Defaults.Key("observeCodableKeyCombine", default: fixtureCodable) diff --git a/readme.md b/readme.md index 11c7056..0cce272 100644 --- a/readme.md +++ b/readme.md @@ -80,6 +80,7 @@ Add `https://github.com/sindresorhus/Defaults` in the [“Swift Package Manager - `NSColor` (macOS) - `UIColor` (iOS) - `Codable` +- `NSSecureCoding` Defaults also support the above types wrapped in `Array`, `Set`, `Dictionary`, and even wrapped in nested types. For example, `[[String: Set<[String: Int]>]]`. @@ -87,6 +88,8 @@ For more types, see the [enum example](#enum-example), [`Codable` example](#coda You can easily add support for any custom type. +If a type conforms to both `NSSecureCoding` and `Codable`, then `Codable` will be used for the serialization. + ## Usage You declare the defaults keys upfront with type and default value.