首页 > 解决方案 > 当结构扩展返回变异的自我时,不能对不可变值使用变异成员

问题描述

我扩展了 Apple 的 URLRequest 结构:

extension URLRequest {

    mutating func addJSONContentTypeHeader() -> URLRequest {
      setValue("application/json", forHTTPHeaderField: "Content-Type")

      return self
    }

    mutating func addAuthHeader(withT t: String) -> URLRequest {
      setValue(t, forHTTPHeaderField: "Auth")

      return self
    }
}

我可以使用这些方法而不会出现问题,例如:

[...]
return urlRequest.addJSONContentTypeHeader()

但是,以下示例中的类似构建器的模式是不可能的,并从标题返回错误消息:

return urlRequest.addJSONContentTypeHeader().addAuthHeader(withT: token) <--- error:

函数调用返回不可变值。

但是,我确实将扩展方法标记为“变异”。避免这种情况的唯一方法是创建中间成员:

let mutableRequest = urlRequest.addJSONContentTypeHeader()
return mutableRequest.addAuthHeader(withT: token)

但是,它肯定不如构建器模式的单行解决方案那么优雅。为什么swiftc不允许我这样写?

标签: swiftstruct

解决方案


是的,这很明显,因为如果您查看了文档,那么您会看到这URLRequest是一个struct带有初始化程序的初始化程序,URL它也struct导致返回原始请求的不可变副本。mutating意味着您正在修改调用对象,但它不会返回“可变”对象!

这就是它给出错误的原因。好吧,如果您仍然希望使用相同的方式,那么我有您的代码的修改版本。

extension URLRequest {

    func addJSONContentTypeHeader() -> URLRequest {
        var newRequest = self
        newRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
        return newRequest
    }

    func addAuthHeader(withT t: String) -> URLRequest {
        var newRequest = self
        newRequest.setValue(t, forHTTPHeaderField: "Auth")
        return newRequest
    }
}

用法:

request.addJSONContentTypeHeader().addAuthHeader(withT: "adfakljdhfkjah")

推荐阅读