@@ -45,37 +45,39 @@ open class UserDefaults: NSObject {
45
45
//Force the returned value to an NSObject
46
46
switch CFGetTypeID ( anObj) {
47
47
case CFStringGetTypeID ( ) :
48
- return ( anObj as! CFString ) . _nsObject
48
+ return unsafeBitCast ( anObj, to : NSString . self )
49
49
50
50
case CFNumberGetTypeID ( ) :
51
- return ( anObj as! CFNumber ) . _nsObject
51
+ return unsafeBitCast ( anObj, to : NSNumber . self )
52
52
53
53
case CFURLGetTypeID ( ) :
54
- return ( anObj as! CFURL ) . _nsObject
54
+ return unsafeBitCast ( anObj, to : NSURL . self )
55
55
56
56
case CFArrayGetTypeID ( ) :
57
- return ( anObj as! CFArray ) . _nsObject
57
+ return unsafeBitCast ( anObj, to : NSArray . self )
58
58
59
59
case CFDictionaryGetTypeID ( ) :
60
- return ( anObj as! CFDictionary ) . _nsObject
61
-
60
+ return unsafeBitCast ( anObj, to : NSDictionary . self )
61
+
62
62
case CFDataGetTypeID ( ) :
63
- return ( anObj as! CFData ) . _nsObject
63
+ return unsafeBitCast ( anObj, to : NSData . self )
64
64
65
65
default :
66
66
return getFromRegistered ( )
67
67
}
68
68
}
69
+
69
70
open func set( _ value: Any ? , forKey defaultName: String ) {
70
71
guard let value = value else {
71
72
CFPreferencesSetAppValue ( defaultName. _cfObject, nil , suite? . _cfObject ?? kCFPreferencesCurrentApplication)
72
73
return
73
74
}
74
75
75
- var cfType : CFTypeRef ? = nil
76
+ let cfType : CFTypeRef
76
77
77
- //FIXME: is this needed? Am I overcomplicating things?
78
- //Foundation types
78
+ // Convert the input value to the internal representation. All values are
79
+ // represented as CFTypeRef objects internally because we store the defaults
80
+ // in a CFPreferences type.
79
81
if let bType = value as? NSNumber {
80
82
cfType = bType. _cfObject
81
83
} else if let bType = value as? NSString {
@@ -84,11 +86,26 @@ open class UserDefaults: NSObject {
84
86
cfType = bType. _cfObject
85
87
} else if let bType = value as? NSDictionary {
86
88
cfType = bType. _cfObject
89
+ } else if let bType = value as? NSData {
90
+ cfType = bType. _cfObject
91
+ } else if let bType = value as? NSURL {
92
+ set ( URL ( reference: bType) , forKey: defaultName)
93
+ return
94
+ } else if let bType = value as? String {
95
+ cfType = bType. _cfObject
87
96
} else if let bType = value as? URL {
88
97
set ( bType, forKey: defaultName)
89
98
return
99
+ } else if let bType = value as? Int {
100
+ var cfValue = Int64 ( bType)
101
+ cfType = CFNumberCreate ( nil , kCFNumberSInt64Type, & cfValue)
102
+ } else if let bType = value as? Double {
103
+ var cfValue = bType
104
+ cfType = CFNumberCreate ( nil , kCFNumberDoubleType, & cfValue)
90
105
} else if let bType = value as? Data {
91
106
cfType = bType. _cfObject
107
+ } else {
108
+ fatalError ( " The type of 'value' passed to UserDefaults.set(forKey:) is not supported. " )
92
109
}
93
110
94
111
CFPreferencesSetAppValue ( defaultName. _cfObject, cfType, suite? . _cfObject ?? kCFPreferencesCurrentApplication)
@@ -140,10 +157,10 @@ open class UserDefaults: NSObject {
140
157
}
141
158
open func data( forKey defaultName: String ) -> Data ? {
142
159
guard let aVal = object ( forKey: defaultName) ,
143
- let bVal = aVal as? Data else {
160
+ let bVal = aVal as? NSData else {
144
161
return nil
145
162
}
146
- return bVal
163
+ return Data ( referencing : bVal)
147
164
}
148
165
open func stringArray( forKey defaultName: String ) -> [ String ] ? {
149
166
guard let aVal = object ( forKey: defaultName) ,
@@ -153,39 +170,61 @@ open class UserDefaults: NSObject {
153
170
return _SwiftValue. fetch ( nonOptional: bVal) as? [ String ]
154
171
}
155
172
open func integer( forKey defaultName: String ) -> Int {
156
- guard let aVal = object ( forKey: defaultName) ,
157
- let bVal = aVal as? NSNumber else {
173
+ guard let aVal = object ( forKey: defaultName) else {
158
174
return 0
159
175
}
160
- return bVal. intValue
176
+ if let bVal = aVal as? NSNumber {
177
+ return bVal. intValue
178
+ }
179
+ if let bVal = aVal as? NSString {
180
+ return bVal. integerValue
181
+ }
182
+ return 0
161
183
}
162
184
open func float( forKey defaultName: String ) -> Float {
163
- guard let aVal = object ( forKey: defaultName) ,
164
- let bVal = aVal as? NSNumber else {
185
+ guard let aVal = object ( forKey: defaultName) else {
165
186
return 0
166
187
}
167
- return bVal. floatValue
188
+ if let bVal = aVal as? NSNumber {
189
+ return bVal. floatValue
190
+ }
191
+ if let bVal = aVal as? NSString {
192
+ return bVal. floatValue
193
+ }
194
+ return 0
168
195
}
169
196
open func double( forKey defaultName: String ) -> Double {
170
- guard let aVal = object ( forKey: defaultName) ,
171
- let bVal = aVal as? NSNumber else {
197
+ guard let aVal = object ( forKey: defaultName) else {
172
198
return 0
173
199
}
174
- return bVal. doubleValue
200
+ if let bVal = aVal as? NSNumber {
201
+ return bVal. doubleValue
202
+ }
203
+ if let bVal = aVal as? NSString {
204
+ return bVal. doubleValue
205
+ }
206
+ return 0
175
207
}
176
208
open func bool( forKey defaultName: String ) -> Bool {
177
- guard let aVal = object ( forKey: defaultName) ,
178
- let bVal = aVal as? NSNumber else {
209
+ guard let aVal = object ( forKey: defaultName) else {
179
210
return false
180
211
}
181
- return bVal. boolValue
212
+ if let bVal = aVal as? NSNumber {
213
+ return bVal. boolValue
214
+ }
215
+ if let bVal = aVal as? NSString {
216
+ return bVal. boolValue
217
+ }
218
+ return false
182
219
}
183
220
open func url( forKey defaultName: String ) -> URL ? {
184
221
guard let aVal = object ( forKey: defaultName) else {
185
222
return nil
186
223
}
187
224
188
- if let bVal = aVal as? NSString {
225
+ if let bVal = aVal as? NSURL {
226
+ return URL ( reference: bVal)
227
+ } else if let bVal = aVal as? NSString {
189
228
let cVal = bVal. expandingTildeInPath
190
229
191
230
return URL ( fileURLWithPath: cVal)
@@ -227,10 +266,32 @@ open class UserDefaults: NSObject {
227
266
228
267
open func register( defaults registrationDictionary: [ String : Any ] ) {
229
268
for (key, value) in registrationDictionary {
230
- registeredDefaults [ key] = value
269
+ let nsValue : NSObject
270
+
271
+ // Converts a value to the internal representation. Internalized values are
272
+ // stored as NSObject derived objects in the registration dictionary.
273
+ if let val = value as? String {
274
+ nsValue = val. _nsObject
275
+ } else if let val = value as? URL {
276
+ nsValue = val. path. _nsObject
277
+ } else if let val = value as? Int {
278
+ nsValue = NSNumber ( value: val)
279
+ } else if let val = value as? Double {
280
+ nsValue = NSNumber ( value: val)
281
+ } else if let val = value as? Bool {
282
+ nsValue = NSNumber ( value: val)
283
+ } else if let val = value as? Data {
284
+ nsValue = val. _nsObject
285
+ } else if let val = value as? NSObject {
286
+ nsValue = val
287
+ } else {
288
+ fatalError ( " The type of 'value' passed to UserDefaults.register(defaults:) is not supported. " )
289
+ }
290
+
291
+ registeredDefaults [ key] = nsValue
231
292
}
232
293
}
233
-
294
+
234
295
open func addSuite( named suiteName: String ) {
235
296
CFPreferencesAddSuitePreferencesToApp ( kCFPreferencesCurrentApplication, suiteName. _cfObject)
236
297
}
0 commit comments