Skip to content

Commit ff652d6

Browse files
alblueparkera
authored andcommitted
Implement missing functions in Date (swiftlang#620)
* Implement missing functions in Date The two NSUnimplemented functions in Date relate to a class property `timeIntervalSinceReferenceDate` which matches an instance property of the same name, and methods relating to the unkeyed coder. Implement the `timeIntervalSinceReferenceDate` by instantiating a new instance and delegating to the instance property, and change the unkeyed coder implementations to a fatalError indicating that they are unsupported. * Guard the use of keyed encoder/decoders Rather than having encode/decode functions with NSUnimplemented, ensure that they have a fatalError to prevent their use intentionally. Change existing code from using `if` to using `guard` to make the patterns more swifty.
1 parent 1f9d6a6 commit ff652d6

9 files changed

+178
-192
lines changed

Diff for: Foundation/NSCalendar.swift

+69-72
Original file line numberDiff line numberDiff line change
@@ -134,26 +134,25 @@ open class NSCalendar : NSObject, NSCopying, NSSecureCoding {
134134
}
135135

136136
public convenience required init?(coder aDecoder: NSCoder) {
137-
if aDecoder.allowsKeyedCoding {
138-
guard let calendarIdentifier = aDecoder.decodeObject(of: NSString.self, forKey: "NS.identifier") else {
139-
return nil
140-
}
141-
142-
self.init(identifier: NSCalendar.Identifier.init(rawValue: calendarIdentifier._swiftObject))
143-
144-
if let timeZone = aDecoder.decodeObject(of: NSTimeZone.self, forKey: "NS.timezone") {
145-
self.timeZone = timeZone._swiftObject
146-
}
147-
if let locale = aDecoder.decodeObject(of: NSLocale.self, forKey: "NS.locale") {
148-
self.locale = locale._swiftObject
149-
}
150-
self.firstWeekday = aDecoder.decodeInteger(forKey: "NS.firstwkdy")
151-
self.minimumDaysInFirstWeek = aDecoder.decodeInteger(forKey: "NS.mindays")
152-
if let startDate = aDecoder.decodeObject(of: NSDate.self, forKey: "NS.gstartdate") {
153-
self._startDate = startDate._swiftObject
154-
}
155-
} else {
156-
NSUnimplemented()
137+
guard aDecoder.allowsKeyedCoding else {
138+
preconditionFailure("Unkeyed coding is unsupported.")
139+
}
140+
guard let calendarIdentifier = aDecoder.decodeObject(of: NSString.self, forKey: "NS.identifier") else {
141+
return nil
142+
}
143+
144+
self.init(identifier: NSCalendar.Identifier.init(rawValue: calendarIdentifier._swiftObject))
145+
146+
if let timeZone = aDecoder.decodeObject(of: NSTimeZone.self, forKey: "NS.timezone") {
147+
self.timeZone = timeZone._swiftObject
148+
}
149+
if let locale = aDecoder.decodeObject(of: NSLocale.self, forKey: "NS.locale") {
150+
self.locale = locale._swiftObject
151+
}
152+
self.firstWeekday = aDecoder.decodeInteger(forKey: "NS.firstwkdy")
153+
self.minimumDaysInFirstWeek = aDecoder.decodeInteger(forKey: "NS.mindays")
154+
if let startDate = aDecoder.decodeObject(of: NSDate.self, forKey: "NS.gstartdate") {
155+
self._startDate = startDate._swiftObject
157156
}
158157
}
159158

@@ -169,16 +168,15 @@ open class NSCalendar : NSObject, NSCopying, NSSecureCoding {
169168
}
170169

171170
open func encode(with aCoder: NSCoder) {
172-
if aCoder.allowsKeyedCoding {
173-
aCoder.encode(self.calendarIdentifier.rawValue._bridgeToObjectiveC(), forKey: "NS.identifier")
174-
aCoder.encode(self.timeZone._nsObject, forKey: "NS.timezone")
175-
aCoder.encode(self.locale?._bridgeToObjectiveC(), forKey: "NS.locale")
176-
aCoder.encode(self.firstWeekday, forKey: "NS.firstwkdy")
177-
aCoder.encode(self.minimumDaysInFirstWeek, forKey: "NS.mindays")
178-
aCoder.encode(self._startDate?._nsObject, forKey: "NS.gstartdate")
179-
} else {
180-
NSUnimplemented()
171+
guard aCoder.allowsKeyedCoding else {
172+
preconditionFailure("Unkeyed coding is unsupported.")
181173
}
174+
aCoder.encode(self.calendarIdentifier.rawValue._bridgeToObjectiveC(), forKey: "NS.identifier")
175+
aCoder.encode(self.timeZone._nsObject, forKey: "NS.timezone")
176+
aCoder.encode(self.locale?._bridgeToObjectiveC(), forKey: "NS.locale")
177+
aCoder.encode(self.firstWeekday, forKey: "NS.firstwkdy")
178+
aCoder.encode(self.minimumDaysInFirstWeek, forKey: "NS.mindays")
179+
aCoder.encode(self._startDate?._nsObject, forKey: "NS.gstartdate")
182180
}
183181

184182
static public var supportsSecureCoding: Bool {
@@ -1373,53 +1371,52 @@ open class NSDateComponents : NSObject, NSCopying, NSSecureCoding {
13731371
}
13741372

13751373
public convenience required init?(coder aDecoder: NSCoder) {
1376-
if aDecoder.allowsKeyedCoding {
1377-
self.init()
1378-
1379-
self.era = aDecoder.decodeInteger(forKey: "NS.era")
1380-
self.year = aDecoder.decodeInteger(forKey: "NS.year")
1381-
self.quarter = aDecoder.decodeInteger(forKey: "NS.quarter")
1382-
self.month = aDecoder.decodeInteger(forKey: "NS.month")
1383-
self.day = aDecoder.decodeInteger(forKey: "NS.day")
1384-
self.hour = aDecoder.decodeInteger(forKey: "NS.hour")
1385-
self.minute = aDecoder.decodeInteger(forKey: "NS.minute")
1386-
self.second = aDecoder.decodeInteger(forKey: "NS.second")
1387-
self.nanosecond = aDecoder.decodeInteger(forKey: "NS.nanosec")
1388-
self.weekOfYear = aDecoder.decodeInteger(forKey: "NS.weekOfYear")
1389-
self.weekOfMonth = aDecoder.decodeInteger(forKey: "NS.weekOfMonth")
1390-
self.yearForWeekOfYear = aDecoder.decodeInteger(forKey: "NS.yearForWOY")
1391-
self.weekday = aDecoder.decodeInteger(forKey: "NS.weekday")
1392-
self.weekdayOrdinal = aDecoder.decodeInteger(forKey: "NS.weekdayOrdinal")
1393-
self.isLeapMonth = aDecoder.decodeBool(forKey: "NS.isLeapMonth")
1394-
self.calendar = aDecoder.decodeObject(of: NSCalendar.self, forKey: "NS.calendar")?._swiftObject
1395-
self.timeZone = aDecoder.decodeObject(of: NSTimeZone.self, forKey: "NS.timezone")?._swiftObject
1396-
} else {
1397-
NSUnimplemented()
1374+
guard aDecoder.allowsKeyedCoding else {
1375+
preconditionFailure("Unkeyed coding is unsupported.")
13981376
}
1377+
1378+
self.init()
1379+
1380+
self.era = aDecoder.decodeInteger(forKey: "NS.era")
1381+
self.year = aDecoder.decodeInteger(forKey: "NS.year")
1382+
self.quarter = aDecoder.decodeInteger(forKey: "NS.quarter")
1383+
self.month = aDecoder.decodeInteger(forKey: "NS.month")
1384+
self.day = aDecoder.decodeInteger(forKey: "NS.day")
1385+
self.hour = aDecoder.decodeInteger(forKey: "NS.hour")
1386+
self.minute = aDecoder.decodeInteger(forKey: "NS.minute")
1387+
self.second = aDecoder.decodeInteger(forKey: "NS.second")
1388+
self.nanosecond = aDecoder.decodeInteger(forKey: "NS.nanosec")
1389+
self.weekOfYear = aDecoder.decodeInteger(forKey: "NS.weekOfYear")
1390+
self.weekOfMonth = aDecoder.decodeInteger(forKey: "NS.weekOfMonth")
1391+
self.yearForWeekOfYear = aDecoder.decodeInteger(forKey: "NS.yearForWOY")
1392+
self.weekday = aDecoder.decodeInteger(forKey: "NS.weekday")
1393+
self.weekdayOrdinal = aDecoder.decodeInteger(forKey: "NS.weekdayOrdinal")
1394+
self.isLeapMonth = aDecoder.decodeBool(forKey: "NS.isLeapMonth")
1395+
self.calendar = aDecoder.decodeObject(of: NSCalendar.self, forKey: "NS.calendar")?._swiftObject
1396+
self.timeZone = aDecoder.decodeObject(of: NSTimeZone.self, forKey: "NS.timezone")?._swiftObject
13991397
}
14001398

14011399
open func encode(with aCoder: NSCoder) {
1402-
if aCoder.allowsKeyedCoding {
1403-
aCoder.encode(self.era, forKey: "NS.era")
1404-
aCoder.encode(self.year, forKey: "NS.year")
1405-
aCoder.encode(self.quarter, forKey: "NS.quarter")
1406-
aCoder.encode(self.month, forKey: "NS.month")
1407-
aCoder.encode(self.day, forKey: "NS.day")
1408-
aCoder.encode(self.hour, forKey: "NS.hour")
1409-
aCoder.encode(self.minute, forKey: "NS.minute")
1410-
aCoder.encode(self.second, forKey: "NS.second")
1411-
aCoder.encode(self.nanosecond, forKey: "NS.nanosec")
1412-
aCoder.encode(self.weekOfYear, forKey: "NS.weekOfYear")
1413-
aCoder.encode(self.weekOfMonth, forKey: "NS.weekOfMonth")
1414-
aCoder.encode(self.yearForWeekOfYear, forKey: "NS.yearForWOY")
1415-
aCoder.encode(self.weekday, forKey: "NS.weekday")
1416-
aCoder.encode(self.weekdayOrdinal, forKey: "NS.weekdayOrdinal")
1417-
aCoder.encode(self.isLeapMonth, forKey: "NS.isLeapMonth")
1418-
aCoder.encode(self.calendar?._nsObject, forKey: "NS.calendar")
1419-
aCoder.encode(self.timeZone?._nsObject, forKey: "NS.timezone")
1420-
} else {
1421-
NSUnimplemented()
1422-
}
1400+
guard aCoder.allowsKeyedCoding else {
1401+
preconditionFailure("Unkeyed coding is unsupported.")
1402+
}
1403+
aCoder.encode(self.era, forKey: "NS.era")
1404+
aCoder.encode(self.year, forKey: "NS.year")
1405+
aCoder.encode(self.quarter, forKey: "NS.quarter")
1406+
aCoder.encode(self.month, forKey: "NS.month")
1407+
aCoder.encode(self.day, forKey: "NS.day")
1408+
aCoder.encode(self.hour, forKey: "NS.hour")
1409+
aCoder.encode(self.minute, forKey: "NS.minute")
1410+
aCoder.encode(self.second, forKey: "NS.second")
1411+
aCoder.encode(self.nanosecond, forKey: "NS.nanosec")
1412+
aCoder.encode(self.weekOfYear, forKey: "NS.weekOfYear")
1413+
aCoder.encode(self.weekOfMonth, forKey: "NS.weekOfMonth")
1414+
aCoder.encode(self.yearForWeekOfYear, forKey: "NS.yearForWOY")
1415+
aCoder.encode(self.weekday, forKey: "NS.weekday")
1416+
aCoder.encode(self.weekdayOrdinal, forKey: "NS.weekdayOrdinal")
1417+
aCoder.encode(self.isLeapMonth, forKey: "NS.isLeapMonth")
1418+
aCoder.encode(self.calendar?._nsObject, forKey: "NS.calendar")
1419+
aCoder.encode(self.timeZone?._nsObject, forKey: "NS.timezone")
14231420
}
14241421

14251422
static public var supportsSecureCoding: Bool {

Diff for: Foundation/NSConcreteValue.swift

+15-17
Original file line numberDiff line numberDiff line change
@@ -118,28 +118,26 @@ internal class NSConcreteValue : NSValue {
118118
}
119119

120120
convenience required init?(coder aDecoder: NSCoder) {
121-
if !aDecoder.allowsKeyedCoding {
122-
NSUnimplemented()
123-
} else {
124-
guard let type = aDecoder.decodeObject() as? NSString else {
125-
return nil
126-
}
127-
128-
let typep = type._swiftObject
129-
130-
// FIXME: This will result in reading garbage memory.
131-
self.init(bytes: [], objCType: typep)
132-
aDecoder.decodeValue(ofObjCType: typep, at: self.value)
121+
guard aDecoder.allowsKeyedCoding else {
122+
preconditionFailure("Unkeyed coding is unsupported.")
133123
}
124+
guard let type = aDecoder.decodeObject() as? NSString else {
125+
return nil
126+
}
127+
128+
let typep = type._swiftObject
129+
130+
// FIXME: This will result in reading garbage memory.
131+
self.init(bytes: [], objCType: typep)
132+
aDecoder.decodeValue(ofObjCType: typep, at: self.value)
134133
}
135134

136135
override func encode(with aCoder: NSCoder) {
137-
if !aCoder.allowsKeyedCoding {
138-
NSUnimplemented()
139-
} else {
140-
aCoder.encode(String(cString: self.objCType)._bridgeToObjectiveC())
141-
aCoder.encodeValue(ofObjCType: self.objCType, at: self.value)
136+
guard aCoder.allowsKeyedCoding else {
137+
preconditionFailure("Unkeyed coding is unsupported.")
142138
}
139+
aCoder.encode(String(cString: self.objCType)._bridgeToObjectiveC())
140+
aCoder.encodeValue(ofObjCType: self.objCType, at: self.value)
143141
}
144142

145143
private var _size : Int {

Diff for: Foundation/NSDate.swift

+11-15
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ open class NSDate : NSObject, NSCopying, NSSecureCoding, NSCoding {
5252
return _timeIntervalSinceReferenceDate
5353
}
5454

55-
open class var timeIntervalSinceReferenceDate: TimeInterval { NSUnimplemented() }
55+
open class var timeIntervalSinceReferenceDate: TimeInterval {
56+
return Date().timeIntervalSinceReferenceDate
57+
}
5658

5759
public convenience override init() {
5860
var tv = timeval()
@@ -69,18 +71,13 @@ open class NSDate : NSObject, NSCopying, NSSecureCoding, NSCoding {
6971
}
7072

7173
public convenience required init?(coder aDecoder: NSCoder) {
72-
if aDecoder.allowsKeyedCoding {
73-
let ti = aDecoder.decodeDouble(forKey: "NS.time")
74-
self.init(timeIntervalSinceReferenceDate: ti)
75-
} else {
76-
var ti: TimeInterval = 0.0
77-
withUnsafeMutablePointer(to: &ti) { (ptr: UnsafeMutablePointer<Double>) -> Void in
78-
aDecoder.decodeValue(ofObjCType: "d", at: UnsafeMutableRawPointer(ptr))
79-
}
80-
self.init(timeIntervalSinceReferenceDate: ti)
74+
guard aDecoder.allowsKeyedCoding else {
75+
preconditionFailure("Unkeyed coding is unsupported.")
8176
}
77+
let ti = aDecoder.decodeDouble(forKey: "NS.time")
78+
self.init(timeIntervalSinceReferenceDate: ti)
8279
}
83-
80+
8481
open override func copy() -> Any {
8582
return copy(with: nil)
8683
}
@@ -94,11 +91,10 @@ open class NSDate : NSObject, NSCopying, NSSecureCoding, NSCoding {
9491
}
9592

9693
open func encode(with aCoder: NSCoder) {
97-
if aCoder.allowsKeyedCoding {
98-
aCoder.encode(_timeIntervalSinceReferenceDate, forKey: "NS.time")
99-
} else {
100-
NSUnimplemented()
94+
guard aCoder.allowsKeyedCoding else {
95+
preconditionFailure("Unkeyed coding is unsupported.")
10196
}
97+
aCoder.encode(_timeIntervalSinceReferenceDate, forKey: "NS.time")
10298
}
10399

104100
/**

Diff for: Foundation/NSGeometry.swift

+21-25
Original file line numberDiff line numberDiff line change
@@ -282,25 +282,23 @@ extension NSEdgeInsets: NSSpecialValueCoding {
282282
}
283283

284284
init?(coder aDecoder: NSCoder) {
285-
if aDecoder.allowsKeyedCoding {
286-
self.top = aDecoder._decodeCGFloatForKey("NS.edgeval.top")
287-
self.left = aDecoder._decodeCGFloatForKey("NS.edgeval.left")
288-
self.bottom = aDecoder._decodeCGFloatForKey("NS.edgeval.bottom")
289-
self.right = aDecoder._decodeCGFloatForKey("NS.edgeval.right")
290-
} else {
291-
NSUnimplemented()
285+
guard aDecoder.allowsKeyedCoding else {
286+
preconditionFailure("Unkeyed coding is unsupported.")
292287
}
288+
self.top = aDecoder._decodeCGFloatForKey("NS.edgeval.top")
289+
self.left = aDecoder._decodeCGFloatForKey("NS.edgeval.left")
290+
self.bottom = aDecoder._decodeCGFloatForKey("NS.edgeval.bottom")
291+
self.right = aDecoder._decodeCGFloatForKey("NS.edgeval.right")
293292
}
294293

295294
func encodeWithCoder(_ aCoder: NSCoder) {
296-
if aCoder.allowsKeyedCoding {
297-
aCoder._encodeCGFloat(self.top, forKey: "NS.edgeval.top")
298-
aCoder._encodeCGFloat(self.left, forKey: "NS.edgeval.left")
299-
aCoder._encodeCGFloat(self.bottom, forKey: "NS.edgeval.bottom")
300-
aCoder._encodeCGFloat(self.right, forKey: "NS.edgeval.right")
301-
} else {
302-
NSUnimplemented()
295+
guard aCoder.allowsKeyedCoding else {
296+
preconditionFailure("Unkeyed coding is unsupported.")
303297
}
298+
aCoder._encodeCGFloat(self.top, forKey: "NS.edgeval.top")
299+
aCoder._encodeCGFloat(self.left, forKey: "NS.edgeval.left")
300+
aCoder._encodeCGFloat(self.bottom, forKey: "NS.edgeval.bottom")
301+
aCoder._encodeCGFloat(self.right, forKey: "NS.edgeval.right")
304302
}
305303

306304
static func objCType() -> String {
@@ -884,22 +882,20 @@ extension NSCoder {
884882

885883
private extension NSCoder {
886884
func _encodeCGFloat(_ value: CGFloat) {
887-
if let keyedArchiver = self as? NSKeyedArchiver {
888-
keyedArchiver._encodeValue(NSNumber(value: value.native))
889-
} else {
890-
NSUnimplemented()
885+
guard let keyedArchiver = self as? NSKeyedArchiver else {
886+
preconditionFailure("Unkeyed coding is unsupported.")
891887
}
888+
keyedArchiver._encodeValue(NSNumber(value: value.native))
892889
}
893890

894891
func _decodeCGFloat() -> CGFloat {
895-
if let keyedUnarchiver = self as? NSKeyedUnarchiver {
896-
guard let result : NSNumber = keyedUnarchiver._decodeValue() else {
897-
return CGFloat(0.0)
898-
}
899-
return CGFloat(result.doubleValue)
900-
} else {
901-
NSUnimplemented()
892+
guard let keyedUnarchiver = self as? NSKeyedUnarchiver else {
893+
preconditionFailure("Unkeyed coding is unsupported.")
894+
}
895+
guard let result : NSNumber = keyedUnarchiver._decodeValue() else {
896+
return CGFloat(0.0)
902897
}
898+
return CGFloat(result.doubleValue)
903899
}
904900

905901
func _encodeCGFloat(_ value: CGFloat, forKey key: String) {

Diff for: Foundation/NSLocale.swift

+10-12
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,13 @@ open class NSLocale: NSObject, NSCopying, NSSecureCoding {
4141
}
4242

4343
public required convenience init?(coder aDecoder: NSCoder) {
44-
if aDecoder.allowsKeyedCoding {
45-
guard let identifier = aDecoder.decodeObject(of: NSString.self, forKey: "NS.identifier") else {
46-
return nil
47-
}
48-
self.init(localeIdentifier: String._unconditionallyBridgeFromObjectiveC(identifier))
49-
} else {
50-
NSUnimplemented()
44+
guard aDecoder.allowsKeyedCoding else {
45+
preconditionFailure("Unkeyed coding is unsupported.")
5146
}
47+
guard let identifier = aDecoder.decodeObject(of: NSString.self, forKey: "NS.identifier") else {
48+
return nil
49+
}
50+
self.init(localeIdentifier: String._unconditionallyBridgeFromObjectiveC(identifier))
5251
}
5352

5453
open override func copy() -> Any {
@@ -68,12 +67,11 @@ open class NSLocale: NSObject, NSCopying, NSSecureCoding {
6867
}
6968

7069
open func encode(with aCoder: NSCoder) {
71-
if aCoder.allowsKeyedCoding {
72-
let identifier = CFLocaleGetIdentifier(self._cfObject)._nsObject
73-
aCoder.encode(identifier, forKey: "NS.identifier")
74-
} else {
75-
NSUnimplemented()
70+
guard aCoder.allowsKeyedCoding else {
71+
preconditionFailure("Unkeyed coding is unsupported.")
7672
}
73+
let identifier = CFLocaleGetIdentifier(self._cfObject)._nsObject
74+
aCoder.encode(identifier, forKey: "NS.identifier")
7775
}
7876

7977
public static var supportsSecureCoding: Bool {

0 commit comments

Comments
 (0)