diff --git a/Sources/UserDefaults+Codable.swift b/Sources/UserDefaults+Codable.swift index 337b349..09433ff 100644 --- a/Sources/UserDefaults+Codable.swift +++ b/Sources/UserDefaults+Codable.swift @@ -45,6 +45,14 @@ public extension UserDefaults { func decode(_ type: T.Type = T.self, forKey key: String) throws -> T? { guard let storage = object(forKey: key) else { return nil } - return try KeyValueDecoder.makePlistCompatible().decode(type, from: storage) + switch type { + case is String.Type: return string(forKey: key) as? T + case is Bool.Type: return bool(forKey: key) as? T + case is Int.Type: return integer(forKey: key) as? T + case is Double.Type: return double(forKey: key) as? T + case is Float.Type: return float(forKey: key) as? T + case is URL.Type: return url(forKey: key) as? T + default: return try KeyValueDecoder.makePlistCompatible().decode(type, from: storage) + } } } diff --git a/Tests/UserDefaults+CodableTests.swift b/Tests/UserDefaults+CodableTests.swift index 9ecfb81..d9940ea 100644 --- a/Tests/UserDefaults+CodableTests.swift +++ b/Tests/UserDefaults+CodableTests.swift @@ -176,6 +176,153 @@ final class UserDefaultsCodableTests: XCTestCase { ) ) } + + func testDecodes_String() { + let defaults = UserDefaults.makeMock() + + defaults.set("YES", forKey: "flag") + XCTAssertEqual( + defaults.string(forKey: "flag"), + "YES" + ) + XCTAssertEqual( + try defaults.decode(String.self, forKey: "flag"), + "YES" + ) + + #if canImport(Darwin) + defaults.set(1, forKey: "flag") + XCTAssertEqual( + defaults.string(forKey: "flag"), + "1" + ) + XCTAssertEqual( + try defaults.decode(String.self, forKey: "flag"), + "1" + ) + #endif + } + + func testDecodes_Bool() { + let defaults = UserDefaults.makeMock() + + defaults.set("YES", forKey: "flag") + XCTAssertTrue(defaults.bool(forKey: "flag")) + XCTAssertEqual( + try defaults.decode(Bool.self, forKey: "flag"), + true + ) + + defaults.set("NO", forKey: "flag") + XCTAssertFalse(defaults.bool(forKey: "flag")) + XCTAssertEqual( + try defaults.decode(Bool.self, forKey: "flag"), + false + ) + + defaults.set("other", forKey: "flag") + XCTAssertFalse(defaults.bool(forKey: "flag")) + XCTAssertEqual( + try defaults.decode(Bool.self, forKey: "flag"), + false + ) + } + + func testDecodes_Integer() { + let defaults = UserDefaults.makeMock() + + defaults.set(1, forKey: "flag") + XCTAssertEqual( + defaults.integer(forKey: "flag"), + 1 + ) + XCTAssertEqual( + try defaults.decode(Int.self, forKey: "flag"), + 1 + ) + + defaults.set("2", forKey: "flag") + XCTAssertEqual( + defaults.integer(forKey: "flag"), + 2 + ) + XCTAssertEqual( + try defaults.decode(Int.self, forKey: "flag"), + 2 + ) + } + + func testDecodes_Double() { + let defaults = UserDefaults.makeMock() + + defaults.set(Double(1.5), forKey: "flag") + XCTAssertEqual( + defaults.double(forKey: "flag"), + 1.5 + ) + XCTAssertEqual( + try defaults.decode(Double.self, forKey: "flag"), + 1.5 + ) + + defaults.set("2.5", forKey: "flag") + XCTAssertEqual( + defaults.double(forKey: "flag"), + 2.5 + ) + XCTAssertEqual( + try defaults.decode(Double.self, forKey: "flag"), + 2.5 + ) + } + + func testDecodes_Float() { + let defaults = UserDefaults.makeMock() + + defaults.set(Float(1.5), forKey: "flag") + XCTAssertEqual( + defaults.float(forKey: "flag"), + 1.5 + ) + XCTAssertEqual( + try defaults.decode(Float.self, forKey: "flag"), + 1.5 + ) + + defaults.set("2.5", forKey: "flag") + XCTAssertEqual( + defaults.float(forKey: "flag"), + 2.5 + ) + XCTAssertEqual( + try defaults.decode(Float.self, forKey: "flag"), + 2.5 + ) + } + + func testDecodes_URL() { + let defaults = UserDefaults.makeMock() + + defaults.set(URL(fileURLWithPath: "/fish"), forKey: "flag") + XCTAssertEqual( + defaults.url(forKey: "flag"), + URL(fileURLWithPath: "/fish") + ) + XCTAssertEqual( + try defaults.decode(URL.self, forKey: "flag"), + URL(fileURLWithPath: "/fish") + ) + + defaults.set("/chips", forKey: "flag") + XCTAssertEqual( + defaults.url(forKey: "flag"), + URL(fileURLWithPath: "/chips") + ) + XCTAssertEqual( + try defaults.decode(URL.self, forKey: "flag"), + URL(fileURLWithPath: "/chips") + ) + } } private extension UserDefaults {