Skip to content

Commit 4dee17b

Browse files
committed
Support Implicit Member Expression for Key #9 #13
1 parent 32a4564 commit 4dee17b

File tree

6 files changed

+97
-45
lines changed

6 files changed

+97
-45
lines changed

DefaultsKit.xcodeproj/project.pbxproj

+16
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
A0AC4AAF1F43853D0070F91D /* DefaultsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC4AAE1F43853D0070F91D /* DefaultsTests.swift */; };
1212
A0AC4AB11F43853D0070F91D /* DefaultsKit.h in Headers */ = {isa = PBXBuildFile; fileRef = A0AC4AA31F43853D0070F91D /* DefaultsKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
1313
A0AC4ABB1F4385500070F91D /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC4ABA1F4385500070F91D /* Defaults.swift */; };
14+
A0DFDB0A20CD8C4F004A4C2F /* DefaultsKey + keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0DFDB0920CD8C4E004A4C2F /* DefaultsKey + keys.swift */; };
15+
A0DFDB0B20CD8C4F004A4C2F /* DefaultsKey + keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0DFDB0920CD8C4E004A4C2F /* DefaultsKey + keys.swift */; };
16+
A0DFDB0C20CD8C4F004A4C2F /* DefaultsKey + keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0DFDB0920CD8C4E004A4C2F /* DefaultsKey + keys.swift */; };
17+
A0DFDB0E20CD8C58004A4C2F /* PersonMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0DFDB0D20CD8C58004A4C2F /* PersonMock.swift */; };
18+
A0DFDB0F20CD8C58004A4C2F /* PersonMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0DFDB0D20CD8C58004A4C2F /* PersonMock.swift */; };
19+
A0DFDB1020CD8C58004A4C2F /* PersonMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0DFDB0D20CD8C58004A4C2F /* PersonMock.swift */; };
1420
A0F000F61F48CEE500617715 /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC4ABA1F4385500070F91D /* Defaults.swift */; };
1521
A0F001041F48CF9D00617715 /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0AC4ABA1F4385500070F91D /* Defaults.swift */; };
1622
A0F0011E1F48D0BD00617715 /* DefaultsKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0F000E91F48CECE00617715 /* DefaultsKit.framework */; };
@@ -51,6 +57,8 @@
5157
A0AC4AAE1F43853D0070F91D /* DefaultsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultsTests.swift; sourceTree = "<group>"; };
5258
A0AC4AB01F43853D0070F91D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5359
A0AC4ABA1F4385500070F91D /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = "<group>"; };
60+
A0DFDB0920CD8C4E004A4C2F /* DefaultsKey + keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DefaultsKey + keys.swift"; sourceTree = "<group>"; };
61+
A0DFDB0D20CD8C58004A4C2F /* PersonMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonMock.swift; sourceTree = "<group>"; };
5462
A0F000E91F48CECE00617715 /* DefaultsKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DefaultsKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5563
A0F000FC1F48CF8200617715 /* DefaultsKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DefaultsKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5664
A0F001191F48D0BD00617715 /* DefaultsKit macOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "DefaultsKit macOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -141,8 +149,10 @@
141149
A0AC4AAD1F43853D0070F91D /* Tests */ = {
142150
isa = PBXGroup;
143151
children = (
152+
A0DFDB0920CD8C4E004A4C2F /* DefaultsKey + keys.swift */,
144153
A0AC4AAE1F43853D0070F91D /* DefaultsTests.swift */,
145154
A0AC4AB01F43853D0070F91D /* Info.plist */,
155+
A0DFDB0D20CD8C58004A4C2F /* PersonMock.swift */,
146156
);
147157
path = Tests;
148158
sourceTree = "<group>";
@@ -396,6 +406,8 @@
396406
buildActionMask = 2147483647;
397407
files = (
398408
A0AC4AAF1F43853D0070F91D /* DefaultsTests.swift in Sources */,
409+
A0DFDB0A20CD8C4F004A4C2F /* DefaultsKey + keys.swift in Sources */,
410+
A0DFDB0E20CD8C58004A4C2F /* PersonMock.swift in Sources */,
399411
);
400412
runOnlyForDeploymentPostprocessing = 0;
401413
};
@@ -420,6 +432,8 @@
420432
buildActionMask = 2147483647;
421433
files = (
422434
A0F001271F48D12900617715 /* DefaultsTests.swift in Sources */,
435+
A0DFDB0C20CD8C4F004A4C2F /* DefaultsKey + keys.swift in Sources */,
436+
A0DFDB1020CD8C58004A4C2F /* PersonMock.swift in Sources */,
423437
);
424438
runOnlyForDeploymentPostprocessing = 0;
425439
};
@@ -428,6 +442,8 @@
428442
buildActionMask = 2147483647;
429443
files = (
430444
A0F001381F48D35700617715 /* DefaultsTests.swift in Sources */,
445+
A0DFDB0B20CD8C4F004A4C2F /* DefaultsKey + keys.swift in Sources */,
446+
A0DFDB0F20CD8C58004A4C2F /* PersonMock.swift in Sources */,
431447
);
432448
runOnlyForDeploymentPostprocessing = 0;
433449
};

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,20 @@ if defaults.has(key) {
4141
```
4242
> If you just need to know that a key/value pair exists, **without actually using the value**, use the `has()` method instead of the optional `get(for:key)`. For complex objects it will prevent any unnecessary deserialization.
4343
44+
### Implicit Member Expression
45+
46+
You can find a convenience wrapper for your keys by extending `DefaultsKey`. This allows you use [Implicit Member Expression](https://docs.swift.org/swift-book/ReferenceManual/Expressions.html#//appleref/swift/grammar/implicit-member-expression):
47+
```swift
48+
// Extend with a custom key
49+
extension DefaultsKey {
50+
static let someKey = Key<String>("someKey")
51+
}
52+
53+
// Then use it like this
54+
defaults.set("Some key", for: .someKey)
55+
defaults.get(for: .someKey) // Output: Some key
56+
```
57+
4458
### Complex objects
4559

4660
To store a complex object just conform to the [Codable](https://developer.apple.com/documentation/swift/codable) protocol:

Sources/Defaults.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424

2525
import Foundation
2626

27+
public class DefaultsKey {}
28+
2729
/// Represents a `Key` with an associated generic value type conforming to the
2830
/// `Codable` protocol.
2931
///
3032
/// static let someKey = Key<ValueType>("someKey")
31-
public final class Key<ValueType: Codable> {
33+
public final class Key<ValueType: Codable>: DefaultsKey {
3234
fileprivate let _key: String
3335
public init(_ key: String) {
3436
_key = key

Tests/DefaultsKey + keys.swift

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// DefaultsKey + keys.swift
3+
// DefaultsKit
4+
//
5+
// Created by Nuno Dias on 10/06/2018.
6+
// Copyright © 2018 Nuno Dias. All rights reserved.
7+
//
8+
9+
import Foundation
10+
@testable import DefaultsKit
11+
12+
extension DefaultsKey {
13+
static let integerKey = Key<Int>("integerKey")
14+
static let floatKey = Key<Float>("floatKey")
15+
static let doubleKey = Key<Double>("doubleKey")
16+
static let stringKey = Key<String>("stringKey")
17+
static let boolKey = Key<Bool>("boolKey")
18+
static let dateKey = Key<Date>("dateKey")
19+
static let arrayOfIntegersKey = Key<[Int]>("arrayOfIntegersKey")
20+
static let personMockKey = Key<PersonMock>("personMockKey")
21+
}

Tests/DefaultsTests.swift

+28-44
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,15 @@ class DefaultsKitTests: XCTestCase {
4343

4444
// Given
4545
let value = 123
46-
let key = Key<Int>("key")
4746

4847
// When
49-
defaults.set(value, for: key)
48+
defaults.set(value, for: .integerKey)
5049

5150
// Then
52-
let hasKey = defaults.has(key)
51+
let hasKey = defaults.has(.integerKey)
5352
XCTAssertTrue(hasKey)
5453

55-
let savedValue = defaults.get(for: key)
54+
let savedValue = defaults.get(for: .integerKey)
5655
XCTAssertEqual(savedValue, value)
5756

5857
}
@@ -61,16 +60,15 @@ class DefaultsKitTests: XCTestCase {
6160

6261
// Given
6362
let value: Float = 123.1
64-
let key = Key<Float>("key")
6563

6664
// When
67-
defaults.set(value, for: key)
65+
defaults.set(value, for: .floatKey)
6866

6967
// Then
70-
let hasKey = defaults.has(key)
68+
let hasKey = defaults.has(.floatKey)
7169
XCTAssertTrue(hasKey)
7270

73-
let savedValue = defaults.get(for: key)
71+
let savedValue = defaults.get(for: .floatKey)
7472
XCTAssertEqual(savedValue, value)
7573

7674
}
@@ -79,16 +77,15 @@ class DefaultsKitTests: XCTestCase {
7977

8078
// Given
8179
let value: Double = 123.1
82-
let key = Key<Double>("key")
8380

8481
// When
85-
defaults.set(value, for: key)
82+
defaults.set(value, for: .doubleKey)
8683

8784
// Then
88-
let hasKey = defaults.has(key)
85+
let hasKey = defaults.has(.doubleKey)
8986
XCTAssertTrue(hasKey)
9087

91-
let savedValue = defaults.get(for: key)
88+
let savedValue = defaults.get(for: .doubleKey)
9289
XCTAssertEqual(savedValue, value)
9390

9491
}
@@ -97,16 +94,15 @@ class DefaultsKitTests: XCTestCase {
9794

9895
// Given
9996
let value = "a string"
100-
let key = Key<String>("key")
10197

10298
// When
103-
defaults.set(value, for: key)
99+
defaults.set(value, for: .stringKey)
104100

105101
// Then
106-
let hasKey = defaults.has(key)
102+
let hasKey = defaults.has(.stringKey)
107103
XCTAssertTrue(hasKey)
108104

109-
let savedValue = defaults.get(for: key)
105+
let savedValue = defaults.get(for: .stringKey)
110106
XCTAssertEqual(savedValue, value)
111107

112108
}
@@ -115,16 +111,15 @@ class DefaultsKitTests: XCTestCase {
115111

116112
// Given
117113
let value = true
118-
let key = Key<Bool>("key")
119114

120115
// When
121-
defaults.set(value, for: key)
116+
defaults.set(value, for: .boolKey)
122117

123118
// Then
124-
let hasKey = defaults.has(key)
119+
let hasKey = defaults.has(.boolKey)
125120
XCTAssertTrue(hasKey)
126121

127-
let savedValue = defaults.get(for: key)
122+
let savedValue = defaults.get(for: .boolKey)
128123
XCTAssertEqual(savedValue, value)
129124

130125
}
@@ -133,16 +128,15 @@ class DefaultsKitTests: XCTestCase {
133128

134129
// Given
135130
let value = Date()
136-
let key = Key<Date>("key")
137131

138132
// When
139-
defaults.set(value, for: key)
133+
defaults.set(value, for: .dateKey)
140134

141135
// Then
142-
let hasKey = defaults.has(key)
136+
let hasKey = defaults.has(.dateKey)
143137
XCTAssertTrue(hasKey)
144138

145-
let savedValue = defaults.get(for: key)
139+
let savedValue = defaults.get(for: .dateKey)
146140
XCTAssertEqual(savedValue, value)
147141

148142
}
@@ -151,16 +145,15 @@ class DefaultsKitTests: XCTestCase {
151145

152146
// Given
153147
let values = [1,2,3,4]
154-
let key = Key<[Int]>("key")
155148

156149
// When
157-
defaults.set(values, for: key)
150+
defaults.set(values, for: .arrayOfIntegersKey)
158151

159152
// Then
160-
let hasKey = defaults.has(key)
153+
let hasKey = defaults.has(.arrayOfIntegersKey)
161154
XCTAssertTrue(hasKey)
162155

163-
let savedValues = defaults.get(for: key)
156+
let savedValues = defaults.get(for: .arrayOfIntegersKey)
164157
XCTAssertNotNil(savedValues)
165158
savedValues?.forEach({ (value) in
166159
XCTAssertTrue(savedValues?.contains(value) ?? false)
@@ -172,43 +165,34 @@ class DefaultsKitTests: XCTestCase {
172165

173166
// Given
174167
let values = [1,2,3,4]
175-
let key = Key<[Int]>("key")
176168

177169
// When
178-
defaults.set(values, for: key)
179-
defaults.clear(key)
170+
defaults.set(values, for: .arrayOfIntegersKey)
171+
defaults.clear(.arrayOfIntegersKey)
180172

181173
// Then
182-
let hasKey = defaults.has(key)
174+
let hasKey = defaults.has(.arrayOfIntegersKey)
183175
XCTAssertFalse(hasKey)
184176

185-
let savedValues = defaults.get(for: key)
177+
let savedValues = defaults.get(for: .arrayOfIntegersKey)
186178
XCTAssertNil(savedValues)
187179

188180
}
189181

190182
func testSetObject() {
191183

192-
// Mocks
193-
struct PersonMock: Codable {
194-
let name: String
195-
let age: Int
196-
let children: [PersonMock]
197-
}
198-
199184
// Given
200185
let child = PersonMock(name: "Anne Greenwell", age: 30, children: [])
201186
let person = PersonMock(name: "Bonnie Greenwell", age: 80, children: [child])
202-
let key = Key<PersonMock>("personKey")
203187

204188
// When
205-
defaults.set(person, for: key)
189+
defaults.set(person, for: .personMockKey)
206190

207191
// Then
208-
let hasKey = defaults.has(key)
192+
let hasKey = defaults.has(.personMockKey)
209193
XCTAssertTrue(hasKey)
210194

211-
let savedPerson = defaults.get(for: key)
195+
let savedPerson = defaults.get(for: .personMockKey)
212196
XCTAssertEqual(savedPerson?.name, "Bonnie Greenwell")
213197
XCTAssertEqual(savedPerson?.age, 80)
214198
XCTAssertEqual(savedPerson?.children.first?.name, "Anne Greenwell")

Tests/PersonMock.swift

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// PersonMock.swift
3+
// DefaultsKit
4+
//
5+
// Created by Nuno Dias on 10/06/2018.
6+
// Copyright © 2018 Nuno Dias. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
struct PersonMock: Codable {
12+
let name: String
13+
let age: Int
14+
let children: [PersonMock]
15+
}

0 commit comments

Comments
 (0)