7

概述

有 2 个URLRequest,一个有httpBody,一个没有httpBody
然而,当比较时,它表明两者是相等的。

问题

这是预期的行为还是我错过了什么?

代码

let url = URL(string: "www.somevalidURL.com")!

var r1 = URLRequest(url: url)
r1.addValue("Content-Type", forHTTPHeaderField: "application/json; charset=utf-8")
r1.httpBody = makeBody(withParameters: ["email" : "a@b.com"])

var r2 = URLRequest(url: url)
r2.addValue("Content-Type", forHTTPHeaderField: "application/json; charset=utf-8")

if r1 == r2 {
    print("requests are equal")
}
else {
    print("requests are not equal")
}

if r1.httpBody == r2.httpBody {
    print("body is equal")
}
else {
    print("body is not equal")
}

func makeBody(withParameters bodyParameters: [String : Any]?) -> Data? {
    guard let bodyParameters = bodyParameters,
        !bodyParameters.isEmpty else {
            return nil
    }
    let body : Data?
    do {
        body = try JSONSerialization.data(withJSONObject: bodyParameters,
                                          options: .prettyPrinted)
    }
    catch {
        print("Error in creating Web Service Body = \(error)")
        body = nil
    }
    return body
}

输出

requests are equal
body is not equal

Xcode 10
Swift 版本:4.2

4

2 回答 2

11

URLRequest是 Foundation 类型的 Swift 覆盖类型,NSURLRequest因此==最终会调用isEqual().NSURLRequest

Foundation 库是针对非 Apple 平台的开源库,在 NSURLRequest.swift#L252我们发现:

open override func isEqual(_ object: Any?) -> Bool {
    //On macOS this fields do not determine the result:
    //allHTTPHeaderFields
    //timeoutInterval
    //httBody
    //networkServiceType
    //httpShouldUsePipelining
    guard let other = object as? NSURLRequest else { return false }
    return other === self
        || (other.url == self.url
            && other.mainDocumentURL == self.mainDocumentURL
            && other.httpMethod == self.httpMethod
            && other.cachePolicy == self.cachePolicy
            && other.httpBodyStream == self.httpBodyStream
            && other.allowsCellularAccess == self.allowsCellularAccess
            && other.httpShouldHandleCookies == self.httpShouldHandleCookies)

所以这似乎是故意的。

于 2018-09-21T09:19:56.290 回答
0

如果您来到这里想知道为什么您的相同URLRequests 彼此不相等,就像我所做的那样,我发现原因是URLRequests equatable 实现区分httpBody设置为 nil 或默认为 nil。

如果我们执行以下操作:

let request = URLRequest(url: URL(string: "test.com"))
var expectedRequest = URLRequest(url: URL(string: "test.com"))
expectedRequest.httpBody = nil

然后:

request == expectedRequest //false
print(request.httpBody) // nil
request.httpBody = nil
request == expectedRequest //true

显式设置httpBodytonil将解决此问题。事实上,body 是什么并不重要,只是它已被明确设置。

request.httpBody = Data()
request == expectedRequest //true

潜在的解释

正如 Martin 正确指出的那样, Swift 的源代码不包含 httpBody。但是,所有属性(在链接中)都相等(并且都可以作为 NSURLRequests 强制转换)不会返回true(请参阅下面的 lldb 输出)。我只能假设链接代码被覆盖以包含另一个属性,并且在didSet或被willSet调用时对其进行了修改httpBody lldb 终端日志

于 2019-04-16T10:58:54.130 回答