From d96265bf9fab827eb2aa2e12432617a950484865 Mon Sep 17 00:00:00 2001 From: Alex Blewitt Date: Tue, 6 Sep 2016 23:33:30 +0100 Subject: [PATCH 1/2] 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. --- Foundation/NSDate.swift | 24 ++++++++++-------------- TestFoundation/TestNSDate.swift | 9 +++++++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Foundation/NSDate.swift b/Foundation/NSDate.swift index 0c6520a864..81eb512e6f 100644 --- a/Foundation/NSDate.swift +++ b/Foundation/NSDate.swift @@ -52,7 +52,9 @@ open class NSDate : NSObject, NSCopying, NSSecureCoding, NSCoding { return _timeIntervalSinceReferenceDate } - open class var timeIntervalSinceReferenceDate: TimeInterval { NSUnimplemented() } + open class var timeIntervalSinceReferenceDate: TimeInterval { + return Date().timeIntervalSinceReferenceDate + } public convenience override init() { var tv = timeval() @@ -69,16 +71,11 @@ open class NSDate : NSObject, NSCopying, NSSecureCoding, NSCoding { } public convenience required init?(coder aDecoder: NSCoder) { - if aDecoder.allowsKeyedCoding { - let ti = aDecoder.decodeDouble(forKey: "NS.time") - self.init(timeIntervalSinceReferenceDate: ti) - } else { - var ti: TimeInterval = 0.0 - withUnsafeMutablePointer(to: &ti) { (ptr: UnsafeMutablePointer) -> Void in - aDecoder.decodeValue(ofObjCType: "d", at: UnsafeMutableRawPointer(ptr)) - } - self.init(timeIntervalSinceReferenceDate: ti) + guard aDecoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + let ti = aDecoder.decodeDouble(forKey: "NS.time") + self.init(timeIntervalSinceReferenceDate: ti) } open override func copy() -> Any { @@ -94,11 +91,10 @@ open class NSDate : NSObject, NSCopying, NSSecureCoding, NSCoding { } open func encode(with aCoder: NSCoder) { - if aCoder.allowsKeyedCoding { - aCoder.encode(_timeIntervalSinceReferenceDate, forKey: "NS.time") - } else { - NSUnimplemented() + guard aCoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + aCoder.encode(_timeIntervalSinceReferenceDate, forKey: "NS.time") } /** diff --git a/TestFoundation/TestNSDate.swift b/TestFoundation/TestNSDate.swift index f7df44fa95..0f45b6d72f 100644 --- a/TestFoundation/TestNSDate.swift +++ b/TestFoundation/TestNSDate.swift @@ -35,6 +35,7 @@ class TestNSDate : XCTestCase { ("test_LaterDate", test_LaterDate), ("test_Compare", test_Compare), ("test_IsEqualToDate", test_IsEqualToDate), + ("test_timeIntervalSinceReferenceDate", test_timeIntervalSinceReferenceDate), ] } @@ -114,4 +115,12 @@ class TestNSDate : XCTestCase { let d3 = d1 + ti XCTAssertEqual(d2, d3) } + + func test_timeIntervalSinceReferenceDate() { + let d1 = Date().timeIntervalSinceReferenceDate + let sinceReferenceDate = Date.timeIntervalSinceReferenceDate + let d2 = Date().timeIntervalSinceReferenceDate + XCTAssertTrue(d1 <= sinceReferenceDate) + XCTAssertTrue(d2 >= sinceReferenceDate) + } } From 74d9bbd5d55116dd4dbc2e726c29d4f92219223d Mon Sep 17 00:00:00 2001 From: Alex Blewitt Date: Wed, 7 Sep 2016 17:14:03 +0100 Subject: [PATCH 2/2] 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. --- Foundation/NSCalendar.swift | 141 +++++++++++++++---------------- Foundation/NSConcreteValue.swift | 32 ++++--- Foundation/NSDate.swift | 2 +- Foundation/NSGeometry.swift | 46 +++++----- Foundation/NSLocale.swift | 22 +++-- Foundation/NSRange.swift | 34 ++++---- Foundation/NSSpecialValue.swift | 32 +++---- Foundation/NSURL.swift | 28 +++--- 8 files changed, 159 insertions(+), 178 deletions(-) diff --git a/Foundation/NSCalendar.swift b/Foundation/NSCalendar.swift index b838289304..c79355a337 100644 --- a/Foundation/NSCalendar.swift +++ b/Foundation/NSCalendar.swift @@ -134,26 +134,25 @@ open class NSCalendar : NSObject, NSCopying, NSSecureCoding { } public convenience required init?(coder aDecoder: NSCoder) { - if aDecoder.allowsKeyedCoding { - guard let calendarIdentifier = aDecoder.decodeObject(of: NSString.self, forKey: "NS.identifier") else { - return nil - } - - self.init(identifier: NSCalendar.Identifier.init(rawValue: calendarIdentifier._swiftObject)) - - if let timeZone = aDecoder.decodeObject(of: NSTimeZone.self, forKey: "NS.timezone") { - self.timeZone = timeZone._swiftObject - } - if let locale = aDecoder.decodeObject(of: NSLocale.self, forKey: "NS.locale") { - self.locale = locale._swiftObject - } - self.firstWeekday = aDecoder.decodeInteger(forKey: "NS.firstwkdy") - self.minimumDaysInFirstWeek = aDecoder.decodeInteger(forKey: "NS.mindays") - if let startDate = aDecoder.decodeObject(of: NSDate.self, forKey: "NS.gstartdate") { - self._startDate = startDate._swiftObject - } - } else { - NSUnimplemented() + guard aDecoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") + } + guard let calendarIdentifier = aDecoder.decodeObject(of: NSString.self, forKey: "NS.identifier") else { + return nil + } + + self.init(identifier: NSCalendar.Identifier.init(rawValue: calendarIdentifier._swiftObject)) + + if let timeZone = aDecoder.decodeObject(of: NSTimeZone.self, forKey: "NS.timezone") { + self.timeZone = timeZone._swiftObject + } + if let locale = aDecoder.decodeObject(of: NSLocale.self, forKey: "NS.locale") { + self.locale = locale._swiftObject + } + self.firstWeekday = aDecoder.decodeInteger(forKey: "NS.firstwkdy") + self.minimumDaysInFirstWeek = aDecoder.decodeInteger(forKey: "NS.mindays") + if let startDate = aDecoder.decodeObject(of: NSDate.self, forKey: "NS.gstartdate") { + self._startDate = startDate._swiftObject } } @@ -169,16 +168,15 @@ open class NSCalendar : NSObject, NSCopying, NSSecureCoding { } open func encode(with aCoder: NSCoder) { - if aCoder.allowsKeyedCoding { - aCoder.encode(self.calendarIdentifier.rawValue._bridgeToObjectiveC(), forKey: "NS.identifier") - aCoder.encode(self.timeZone._nsObject, forKey: "NS.timezone") - aCoder.encode(self.locale?._bridgeToObjectiveC(), forKey: "NS.locale") - aCoder.encode(self.firstWeekday, forKey: "NS.firstwkdy") - aCoder.encode(self.minimumDaysInFirstWeek, forKey: "NS.mindays") - aCoder.encode(self._startDate?._nsObject, forKey: "NS.gstartdate") - } else { - NSUnimplemented() + guard aCoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + aCoder.encode(self.calendarIdentifier.rawValue._bridgeToObjectiveC(), forKey: "NS.identifier") + aCoder.encode(self.timeZone._nsObject, forKey: "NS.timezone") + aCoder.encode(self.locale?._bridgeToObjectiveC(), forKey: "NS.locale") + aCoder.encode(self.firstWeekday, forKey: "NS.firstwkdy") + aCoder.encode(self.minimumDaysInFirstWeek, forKey: "NS.mindays") + aCoder.encode(self._startDate?._nsObject, forKey: "NS.gstartdate") } static public var supportsSecureCoding: Bool { @@ -1373,53 +1371,52 @@ open class NSDateComponents : NSObject, NSCopying, NSSecureCoding { } public convenience required init?(coder aDecoder: NSCoder) { - if aDecoder.allowsKeyedCoding { - self.init() - - self.era = aDecoder.decodeInteger(forKey: "NS.era") - self.year = aDecoder.decodeInteger(forKey: "NS.year") - self.quarter = aDecoder.decodeInteger(forKey: "NS.quarter") - self.month = aDecoder.decodeInteger(forKey: "NS.month") - self.day = aDecoder.decodeInteger(forKey: "NS.day") - self.hour = aDecoder.decodeInteger(forKey: "NS.hour") - self.minute = aDecoder.decodeInteger(forKey: "NS.minute") - self.second = aDecoder.decodeInteger(forKey: "NS.second") - self.nanosecond = aDecoder.decodeInteger(forKey: "NS.nanosec") - self.weekOfYear = aDecoder.decodeInteger(forKey: "NS.weekOfYear") - self.weekOfMonth = aDecoder.decodeInteger(forKey: "NS.weekOfMonth") - self.yearForWeekOfYear = aDecoder.decodeInteger(forKey: "NS.yearForWOY") - self.weekday = aDecoder.decodeInteger(forKey: "NS.weekday") - self.weekdayOrdinal = aDecoder.decodeInteger(forKey: "NS.weekdayOrdinal") - self.isLeapMonth = aDecoder.decodeBool(forKey: "NS.isLeapMonth") - self.calendar = aDecoder.decodeObject(of: NSCalendar.self, forKey: "NS.calendar")?._swiftObject - self.timeZone = aDecoder.decodeObject(of: NSTimeZone.self, forKey: "NS.timezone")?._swiftObject - } else { - NSUnimplemented() + guard aDecoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + + self.init() + + self.era = aDecoder.decodeInteger(forKey: "NS.era") + self.year = aDecoder.decodeInteger(forKey: "NS.year") + self.quarter = aDecoder.decodeInteger(forKey: "NS.quarter") + self.month = aDecoder.decodeInteger(forKey: "NS.month") + self.day = aDecoder.decodeInteger(forKey: "NS.day") + self.hour = aDecoder.decodeInteger(forKey: "NS.hour") + self.minute = aDecoder.decodeInteger(forKey: "NS.minute") + self.second = aDecoder.decodeInteger(forKey: "NS.second") + self.nanosecond = aDecoder.decodeInteger(forKey: "NS.nanosec") + self.weekOfYear = aDecoder.decodeInteger(forKey: "NS.weekOfYear") + self.weekOfMonth = aDecoder.decodeInteger(forKey: "NS.weekOfMonth") + self.yearForWeekOfYear = aDecoder.decodeInteger(forKey: "NS.yearForWOY") + self.weekday = aDecoder.decodeInteger(forKey: "NS.weekday") + self.weekdayOrdinal = aDecoder.decodeInteger(forKey: "NS.weekdayOrdinal") + self.isLeapMonth = aDecoder.decodeBool(forKey: "NS.isLeapMonth") + self.calendar = aDecoder.decodeObject(of: NSCalendar.self, forKey: "NS.calendar")?._swiftObject + self.timeZone = aDecoder.decodeObject(of: NSTimeZone.self, forKey: "NS.timezone")?._swiftObject } open func encode(with aCoder: NSCoder) { - if aCoder.allowsKeyedCoding { - aCoder.encode(self.era, forKey: "NS.era") - aCoder.encode(self.year, forKey: "NS.year") - aCoder.encode(self.quarter, forKey: "NS.quarter") - aCoder.encode(self.month, forKey: "NS.month") - aCoder.encode(self.day, forKey: "NS.day") - aCoder.encode(self.hour, forKey: "NS.hour") - aCoder.encode(self.minute, forKey: "NS.minute") - aCoder.encode(self.second, forKey: "NS.second") - aCoder.encode(self.nanosecond, forKey: "NS.nanosec") - aCoder.encode(self.weekOfYear, forKey: "NS.weekOfYear") - aCoder.encode(self.weekOfMonth, forKey: "NS.weekOfMonth") - aCoder.encode(self.yearForWeekOfYear, forKey: "NS.yearForWOY") - aCoder.encode(self.weekday, forKey: "NS.weekday") - aCoder.encode(self.weekdayOrdinal, forKey: "NS.weekdayOrdinal") - aCoder.encode(self.isLeapMonth, forKey: "NS.isLeapMonth") - aCoder.encode(self.calendar?._nsObject, forKey: "NS.calendar") - aCoder.encode(self.timeZone?._nsObject, forKey: "NS.timezone") - } else { - NSUnimplemented() - } + guard aCoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") + } + aCoder.encode(self.era, forKey: "NS.era") + aCoder.encode(self.year, forKey: "NS.year") + aCoder.encode(self.quarter, forKey: "NS.quarter") + aCoder.encode(self.month, forKey: "NS.month") + aCoder.encode(self.day, forKey: "NS.day") + aCoder.encode(self.hour, forKey: "NS.hour") + aCoder.encode(self.minute, forKey: "NS.minute") + aCoder.encode(self.second, forKey: "NS.second") + aCoder.encode(self.nanosecond, forKey: "NS.nanosec") + aCoder.encode(self.weekOfYear, forKey: "NS.weekOfYear") + aCoder.encode(self.weekOfMonth, forKey: "NS.weekOfMonth") + aCoder.encode(self.yearForWeekOfYear, forKey: "NS.yearForWOY") + aCoder.encode(self.weekday, forKey: "NS.weekday") + aCoder.encode(self.weekdayOrdinal, forKey: "NS.weekdayOrdinal") + aCoder.encode(self.isLeapMonth, forKey: "NS.isLeapMonth") + aCoder.encode(self.calendar?._nsObject, forKey: "NS.calendar") + aCoder.encode(self.timeZone?._nsObject, forKey: "NS.timezone") } static public var supportsSecureCoding: Bool { diff --git a/Foundation/NSConcreteValue.swift b/Foundation/NSConcreteValue.swift index f79199b719..bcf4cdd100 100644 --- a/Foundation/NSConcreteValue.swift +++ b/Foundation/NSConcreteValue.swift @@ -118,28 +118,26 @@ internal class NSConcreteValue : NSValue { } convenience required init?(coder aDecoder: NSCoder) { - if !aDecoder.allowsKeyedCoding { - NSUnimplemented() - } else { - guard let type = aDecoder.decodeObject() as? NSString else { - return nil - } - - let typep = type._swiftObject - - // FIXME: This will result in reading garbage memory. - self.init(bytes: [], objCType: typep) - aDecoder.decodeValue(ofObjCType: typep, at: self.value) + guard aDecoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + guard let type = aDecoder.decodeObject() as? NSString else { + return nil + } + + let typep = type._swiftObject + + // FIXME: This will result in reading garbage memory. + self.init(bytes: [], objCType: typep) + aDecoder.decodeValue(ofObjCType: typep, at: self.value) } override func encode(with aCoder: NSCoder) { - if !aCoder.allowsKeyedCoding { - NSUnimplemented() - } else { - aCoder.encode(String(cString: self.objCType)._bridgeToObjectiveC()) - aCoder.encodeValue(ofObjCType: self.objCType, at: self.value) + guard aCoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + aCoder.encode(String(cString: self.objCType)._bridgeToObjectiveC()) + aCoder.encodeValue(ofObjCType: self.objCType, at: self.value) } private var _size : Int { diff --git a/Foundation/NSDate.swift b/Foundation/NSDate.swift index 81eb512e6f..17af9812d0 100644 --- a/Foundation/NSDate.swift +++ b/Foundation/NSDate.swift @@ -77,7 +77,7 @@ open class NSDate : NSObject, NSCopying, NSSecureCoding, NSCoding { let ti = aDecoder.decodeDouble(forKey: "NS.time") self.init(timeIntervalSinceReferenceDate: ti) } - + open override func copy() -> Any { return copy(with: nil) } diff --git a/Foundation/NSGeometry.swift b/Foundation/NSGeometry.swift index 073d906242..19bb66f8b7 100644 --- a/Foundation/NSGeometry.swift +++ b/Foundation/NSGeometry.swift @@ -282,25 +282,23 @@ extension NSEdgeInsets: NSSpecialValueCoding { } init?(coder aDecoder: NSCoder) { - if aDecoder.allowsKeyedCoding { - self.top = aDecoder._decodeCGFloatForKey("NS.edgeval.top") - self.left = aDecoder._decodeCGFloatForKey("NS.edgeval.left") - self.bottom = aDecoder._decodeCGFloatForKey("NS.edgeval.bottom") - self.right = aDecoder._decodeCGFloatForKey("NS.edgeval.right") - } else { - NSUnimplemented() + guard aDecoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + self.top = aDecoder._decodeCGFloatForKey("NS.edgeval.top") + self.left = aDecoder._decodeCGFloatForKey("NS.edgeval.left") + self.bottom = aDecoder._decodeCGFloatForKey("NS.edgeval.bottom") + self.right = aDecoder._decodeCGFloatForKey("NS.edgeval.right") } func encodeWithCoder(_ aCoder: NSCoder) { - if aCoder.allowsKeyedCoding { - aCoder._encodeCGFloat(self.top, forKey: "NS.edgeval.top") - aCoder._encodeCGFloat(self.left, forKey: "NS.edgeval.left") - aCoder._encodeCGFloat(self.bottom, forKey: "NS.edgeval.bottom") - aCoder._encodeCGFloat(self.right, forKey: "NS.edgeval.right") - } else { - NSUnimplemented() + guard aCoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + aCoder._encodeCGFloat(self.top, forKey: "NS.edgeval.top") + aCoder._encodeCGFloat(self.left, forKey: "NS.edgeval.left") + aCoder._encodeCGFloat(self.bottom, forKey: "NS.edgeval.bottom") + aCoder._encodeCGFloat(self.right, forKey: "NS.edgeval.right") } static func objCType() -> String { @@ -884,22 +882,20 @@ extension NSCoder { private extension NSCoder { func _encodeCGFloat(_ value: CGFloat) { - if let keyedArchiver = self as? NSKeyedArchiver { - keyedArchiver._encodeValue(NSNumber(value: value.native)) - } else { - NSUnimplemented() + guard let keyedArchiver = self as? NSKeyedArchiver else { + preconditionFailure("Unkeyed coding is unsupported.") } + keyedArchiver._encodeValue(NSNumber(value: value.native)) } func _decodeCGFloat() -> CGFloat { - if let keyedUnarchiver = self as? NSKeyedUnarchiver { - guard let result : NSNumber = keyedUnarchiver._decodeValue() else { - return CGFloat(0.0) - } - return CGFloat(result.doubleValue) - } else { - NSUnimplemented() + guard let keyedUnarchiver = self as? NSKeyedUnarchiver else { + preconditionFailure("Unkeyed coding is unsupported.") + } + guard let result : NSNumber = keyedUnarchiver._decodeValue() else { + return CGFloat(0.0) } + return CGFloat(result.doubleValue) } func _encodeCGFloat(_ value: CGFloat, forKey key: String) { diff --git a/Foundation/NSLocale.swift b/Foundation/NSLocale.swift index 413fbde017..b1230d5026 100644 --- a/Foundation/NSLocale.swift +++ b/Foundation/NSLocale.swift @@ -41,14 +41,13 @@ open class NSLocale: NSObject, NSCopying, NSSecureCoding { } public required convenience init?(coder aDecoder: NSCoder) { - if aDecoder.allowsKeyedCoding { - guard let identifier = aDecoder.decodeObject(of: NSString.self, forKey: "NS.identifier") else { - return nil - } - self.init(localeIdentifier: String._unconditionallyBridgeFromObjectiveC(identifier)) - } else { - NSUnimplemented() + guard aDecoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + guard let identifier = aDecoder.decodeObject(of: NSString.self, forKey: "NS.identifier") else { + return nil + } + self.init(localeIdentifier: String._unconditionallyBridgeFromObjectiveC(identifier)) } open override func copy() -> Any { @@ -68,12 +67,11 @@ open class NSLocale: NSObject, NSCopying, NSSecureCoding { } open func encode(with aCoder: NSCoder) { - if aCoder.allowsKeyedCoding { - let identifier = CFLocaleGetIdentifier(self._cfObject)._nsObject - aCoder.encode(identifier, forKey: "NS.identifier") - } else { - NSUnimplemented() + guard aCoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + let identifier = CFLocaleGetIdentifier(self._cfObject)._nsObject + aCoder.encode(identifier, forKey: "NS.identifier") } public static var supportsSecureCoding: Bool { diff --git a/Foundation/NSRange.swift b/Foundation/NSRange.swift index 37a166ed5b..8b0dff8f14 100644 --- a/Foundation/NSRange.swift +++ b/Foundation/NSRange.swift @@ -61,29 +61,27 @@ extension NSRange: NSSpecialValueCoding { } init?(coder aDecoder: NSCoder) { - if aDecoder.allowsKeyedCoding { - if let location = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.location") { - self.location = location.intValue - } else { - self.location = 0 - } - if let length = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.length") { - self.length = length.intValue - } else { - self.length = 0 - } + guard aDecoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") + } + if let location = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.location") { + self.location = location.intValue + } else { + self.location = 0 + } + if let length = aDecoder.decodeObject(of: NSNumber.self, forKey: "NS.rangeval.length") { + self.length = length.intValue } else { - NSUnimplemented() + self.length = 0 } } - + func encodeWithCoder(_ aCoder: NSCoder) { - if aCoder.allowsKeyedCoding { - aCoder.encode(NSNumber(value: self.location), forKey: "NS.rangeval.location") - aCoder.encode(NSNumber(value: self.length), forKey: "NS.rangeval.length") - } else { - NSUnimplemented() + guard aCoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + aCoder.encode(NSNumber(value: self.location), forKey: "NS.rangeval.location") + aCoder.encode(NSNumber(value: self.length), forKey: "NS.rangeval.length") } static func objCType() -> String { diff --git a/Foundation/NSSpecialValue.swift b/Foundation/NSSpecialValue.swift index 8a78b7903a..af88300983 100644 --- a/Foundation/NSSpecialValue.swift +++ b/Foundation/NSSpecialValue.swift @@ -94,29 +94,25 @@ internal class NSSpecialValue : NSValue { } convenience required init?(coder aDecoder: NSCoder) { - if !aDecoder.allowsKeyedCoding { - NSUnimplemented() - } else { - let specialFlags = aDecoder.decodeInteger(forKey: "NS.special") - guard let specialType = NSSpecialValue._typeFromFlags(specialFlags) else { - return nil - } - - guard let specialValue = specialType.init(coder: aDecoder) else { - return nil - } - - self.init(specialValue) + guard aDecoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + let specialFlags = aDecoder.decodeInteger(forKey: "NS.special") + guard let specialType = NSSpecialValue._typeFromFlags(specialFlags) else { + return nil + } + guard let specialValue = specialType.init(coder: aDecoder) else { + return nil + } + self.init(specialValue) } override func encode(with aCoder: NSCoder) { - if !aCoder.allowsKeyedCoding { - NSUnimplemented() - } else { - aCoder.encode(NSSpecialValue._flagsFromType(type(of: _value)), forKey: "NS.special") - _value.encodeWithCoder(aCoder) + guard aCoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + aCoder.encode(NSSpecialValue._flagsFromType(type(of: _value)), forKey: "NS.special") + _value.encodeWithCoder(aCoder) } override var objCType : UnsafePointer { diff --git a/Foundation/NSURL.swift b/Foundation/NSURL.swift index a571d183d7..417ddb1e65 100644 --- a/Foundation/NSURL.swift +++ b/Foundation/NSURL.swift @@ -283,27 +283,25 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying { public static var supportsSecureCoding: Bool { return true } public convenience required init?(coder aDecoder: NSCoder) { - if aDecoder.allowsKeyedCoding { - let base = aDecoder.decodeObject(of: NSURL.self, forKey:"NS.base")?._swiftObject - let relative = aDecoder.decodeObject(of: NSString.self, forKey:"NS.relative") + guard aDecoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") + } + let base = aDecoder.decodeObject(of: NSURL.self, forKey:"NS.base")?._swiftObject + let relative = aDecoder.decodeObject(of: NSString.self, forKey:"NS.relative") - if relative == nil { - return nil - } - - self.init(string: String._unconditionallyBridgeFromObjectiveC(relative!), relativeTo: base) - } else { - NSUnimplemented() + if relative == nil { + return nil } + + self.init(string: String._unconditionallyBridgeFromObjectiveC(relative!), relativeTo: base) } open func encode(with aCoder: NSCoder) { - if aCoder.allowsKeyedCoding { - aCoder.encode(self.baseURL?._nsObject, forKey:"NS.base") - aCoder.encode(self.relativeString._bridgeToObjectiveC(), forKey:"NS.relative") - } else { - NSUnimplemented() + guard aCoder.allowsKeyedCoding else { + preconditionFailure("Unkeyed coding is unsupported.") } + aCoder.encode(self.baseURL?._nsObject, forKey:"NS.base") + aCoder.encode(self.relativeString._bridgeToObjectiveC(), forKey:"NS.relative") } public init(fileURLWithPath path: String, isDirectory isDir: Bool, relativeTo baseURL: URL?) {