Skip to content

Commit 7d680cd

Browse files
authored
Merge pull request #711 from naithar/URLResponse-NSCoding
2 parents df27829 + 34fb920 commit 7d680cd

File tree

3 files changed

+93
-5
lines changed

3 files changed

+93
-5
lines changed

Docs/Status.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ There is no _Complete_ status for test coverage because there are always additio
5555
| `URLProtocolClient` | Unimplemented | None | |
5656
| `NSURLRequest` | Mostly Complete | Incomplete | |
5757
| `NSMutableURLRequest` | Mostly Complete | Incomplete | |
58-
| `URLResponse` | Mostly Complete | Incomplete | `NSCoding` remains unimplemented |
59-
| `NSHTTPURLResponse` | Mostly Complete | Substantial | `NSCoding` remains unimplemented |
58+
| `URLResponse` | Mostly Complete | Incomplete | |
59+
| `NSHTTPURLResponse` | Mostly Complete | Substantial | |
6060
| `NSURL` | Mostly Complete | Substantial | `NSCoding` with non-keyed-coding archivers, `checkResourceIsReachable()`, and resource values remain unimplemented |
6161
| `NSURLQueryItem` | Mostly Complete | N/A | `NSCoding` remains unimplemented |
6262
| `URLResourceKey` | Complete | N/A | |

Foundation/NSURLResponse.swift

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,39 @@ open class URLResponse : NSObject, NSSecureCoding, NSCopying {
2323
}
2424

2525
public required init?(coder aDecoder: NSCoder) {
26-
NSUnimplemented()
26+
guard aDecoder.allowsKeyedCoding else {
27+
preconditionFailure("Unkeyed coding is unsupported.")
28+
}
29+
30+
if let encodedUrl = aDecoder.decodeObject(forKey: "NS.url") as? NSURL {
31+
self.url = encodedUrl._swiftObject
32+
}
33+
34+
if let encodedMimeType = aDecoder.decodeObject(forKey: "NS.mimeType") as? NSString {
35+
self.mimeType = encodedMimeType._swiftObject
36+
}
37+
38+
self.expectedContentLength = aDecoder.decodeInt64(forKey: "NS.expectedContentLength")
39+
40+
if let encodedEncodingName = aDecoder.decodeObject(forKey: "NS.textEncodingName") as? NSString {
41+
self.textEncodingName = encodedEncodingName._swiftObject
42+
}
43+
44+
if let encodedFilename = aDecoder.decodeObject(forKey: "NS.suggestedFilename") as? NSString {
45+
self.suggestedFilename = encodedFilename._swiftObject
46+
}
2747
}
2848

2949
open func encode(with aCoder: NSCoder) {
30-
NSUnimplemented()
50+
guard aCoder.allowsKeyedCoding else {
51+
preconditionFailure("Unkeyed coding is unsupported.")
52+
}
53+
54+
aCoder.encode(self.url?._bridgeToObjectiveC(), forKey: "NS.url")
55+
aCoder.encode(self.mimeType?._bridgeToObjectiveC(), forKey: "NS.mimeType")
56+
aCoder.encode(self.expectedContentLength, forKey: "NS.expectedContentLength")
57+
aCoder.encode(self.textEncodingName?._bridgeToObjectiveC(), forKey: "NS.textEncodingName")
58+
aCoder.encode(self.suggestedFilename?._bridgeToObjectiveC(), forKey: "NS.suggestedFilename")
3159
}
3260

3361
open override func copy() -> Any {
@@ -135,7 +163,27 @@ open class HTTPURLResponse : URLResponse {
135163
}
136164

137165
public required init?(coder aDecoder: NSCoder) {
138-
NSUnimplemented()
166+
guard aDecoder.allowsKeyedCoding else {
167+
preconditionFailure("Unkeyed coding is unsupported.")
168+
}
169+
170+
self.statusCode = aDecoder.decodeInteger(forKey: "NS.statusCode")
171+
172+
if let encodedHeaders = aDecoder.decodeObject(forKey: "NS.allHeaderFields") as? NSDictionary {
173+
self.allHeaderFields = encodedHeaders._swiftObject
174+
} else {
175+
self.allHeaderFields = [:]
176+
}
177+
178+
super.init(coder: aDecoder)
179+
}
180+
181+
open override func encode(with aCoder: NSCoder) {
182+
super.encode(with: aCoder) //Will fail if .allowsKeyedCoding == false
183+
184+
aCoder.encode(self.statusCode, forKey: "NS.statusCode")
185+
aCoder.encode(self.allHeaderFields._bridgeToObjectiveC(), forKey: "NS.allHeaderFields")
186+
139187
}
140188

141189
/// The HTTP status code of the receiver.

TestFoundation/TestNSURLResponse.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class TestNSURLResponse : XCTestCase {
2929
("test_suggestedFilename_2", test_suggestedFilename_2),
3030
("test_suggestedFilename_3", test_suggestedFilename_3),
3131
("test_copywithzone", test_copyWithZone),
32+
("test_NSCoding", test_NSCoding),
3233
]
3334
}
3435

@@ -91,6 +92,19 @@ class TestNSURLResponse : XCTestCase {
9192
let res = URLResponse(url: url, mimeType: "txt", expectedContentLength: 0, textEncodingName: nil)
9293
XCTAssertTrue(res.isEqual(res.copy() as! NSObject))
9394
}
95+
96+
func test_NSCoding() {
97+
let url = URL(string: "https://apple.com")!
98+
let responseA = URLResponse(url: url, mimeType: "txt", expectedContentLength: 0, textEncodingName: nil)
99+
let responseB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: responseA)) as! URLResponse
100+
101+
//On macOS unarchived Archived then unarchived `URLResponse` is not equal.
102+
XCTAssertEqual(responseA.url, responseB.url, "Archived then unarchived url response must be equal.")
103+
XCTAssertEqual(responseA.mimeType, responseB.mimeType, "Archived then unarchived url response must be equal.")
104+
XCTAssertEqual(responseA.expectedContentLength, responseB.expectedContentLength, "Archived then unarchived url response must be equal.")
105+
XCTAssertEqual(responseA.textEncodingName, responseB.textEncodingName, "Archived then unarchived url response must be equal.")
106+
XCTAssertEqual(responseA.suggestedFilename, responseB.suggestedFilename, "Archived then unarchived url response must be equal.")
107+
}
94108
}
95109

96110

@@ -127,6 +141,8 @@ class TestNSHTTPURLResponse : XCTestCase {
127141
("test_MIMETypeAndCharacterEncoding_1", test_MIMETypeAndCharacterEncoding_1),
128142
("test_MIMETypeAndCharacterEncoding_2", test_MIMETypeAndCharacterEncoding_2),
129143
("test_MIMETypeAndCharacterEncoding_3", test_MIMETypeAndCharacterEncoding_3),
144+
145+
("test_NSCoding", test_NSCoding),
130146
]
131147
}
132148

@@ -292,4 +308,28 @@ class TestNSHTTPURLResponse : XCTestCase {
292308
XCTAssertEqual(sut?.mimeType, "text/html")
293309
XCTAssertEqual(sut?.textEncodingName, "iso-8859-4")
294310
}
311+
312+
// NSCoding
313+
314+
func test_NSCoding() {
315+
let url = URL(string: "https://apple.com")!
316+
let f = ["Content-Type": "text/HTML; charset=ISO-8859-4"]
317+
318+
let responseA = HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: f)!
319+
let responseB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: responseA)) as! HTTPURLResponse
320+
321+
//On macOS unarchived Archived then unarchived `URLResponse` is not equal.
322+
XCTAssertEqual(responseA.statusCode, responseB.statusCode, "Archived then unarchived http url response must be equal.")
323+
XCTAssertEqual(Array(responseA.allHeaderFields.keys), Array(responseB.allHeaderFields.keys), "Archived then unarchived http url response must be equal.")
324+
325+
for key in responseA.allHeaderFields.keys {
326+
XCTAssertEqual(responseA.allHeaderFields[key] as? String, responseB.allHeaderFields[key] as? String, "Archived then unarchived http url response must be equal.")
327+
}
328+
329+
XCTAssertEqual(responseA.url, responseB.url, "Archived then unarchived http url response must be equal.")
330+
XCTAssertEqual(responseA.mimeType, responseB.mimeType, "Archived then unarchived http url response must be equal.")
331+
XCTAssertEqual(responseA.expectedContentLength, responseB.expectedContentLength, "Archived then unarchived http url response must be equal.")
332+
XCTAssertEqual(responseA.textEncodingName, responseB.textEncodingName, "Archived then unarchived http url response must be equal.")
333+
XCTAssertEqual(responseA.suggestedFilename, responseB.suggestedFilename, "Archived then unarchived http url response must be equal.")
334+
}
295335
}

0 commit comments

Comments
 (0)