如何在 Swift 4 中将 NSmutableURLRequest 转换为 URLRequest?

how to convert NSmutableURLRequest to URLRequest in Swift 4?

func requestForAccessToken(authorizationCode: String) {
    let grantType = "authorization_code"
    let redirectURL = "https://com.appcoda.linkedin.oauth/oauth".addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
    // Set the POST parameters.
    var postParams = "grant_type=\(grantType)&"
    postParams += "code=\(authorizationCode)&"
    postParams += "redirect_uri=\(String(describing: redirectURL))&"
    postParams += "client_id=\(linkedInKey)&"
    postParams += "client_secret=\(linkedInSecret)"

    let postData = postParams.data(using: String.Encoding.utf8)
    let request =  NSMutableURLRequest(url: NSURL(string: accessTokenEndPoint)! as URL)
    request.httpMethod = "POST"
    //http body
    request.httpBody = postData
    //headerfield
    request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    // init the session
    let session = URLSession(configuration: URLSessionConfiguration.default)

    let task: URLSessionDataTask = session.dataTask(with: request) { (data, response, error) in
    // Throwing and error it needs a URLRequest at session.dataTask("Here")

    // Below is the error Xcode yells 

    // Ambiguous reference to member 'dataTask(with:completionHandler:)

    }
}

使用如下

 let task: URLSessionDataTask = session.dataTask(with: request as URLRequest ) { (data, response, error) in

}

我想补充几点: 1. 正确解包可选,使用if-let/guard-let。 2. NS大部分时间来自Objective-C,所以去掉NS就是swift(大部分时间)

func requestForAccessToken(authorizationCode: String) {
    let grantType = "authorization_code"
    let redirectURL = "https://com.appcoda.linkedin.oauth/oauth".addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
    var postParams = "grant_type=\(grantType)&"
    postParams += "code=\(authorizationCode)&"
    postParams += "redirect_uri=\(String(describing: redirectURL))&"
    postParams += "client_id=\(linkedInKey)&"
    postParams += "client_secret=\(linkedInSecret)"

    guard let url = URL(string: accessTokenEndPoint) else {
        return
    }
    let postData = postParams.data(using: .utf8) // Suggested by rmaddy
    var request = URLRequest(url: url)
    //let request =  NSMutableURLRequest(url: NSURL(string: accessTokenEndPoint)! as URL)
    request.httpMethod = "POST"
    request.httpBody = postData
    request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    let session = URLSession(configuration: URLSessionConfiguration.default)
    let task: URLSessionDataTask = session.dataTask(with: request) { (data, response, error) in

    }
    task.resume()
}

您可以使用此功能创建 http 正文:

private let linkedInKey = ""
private let linkedInSecret = ""

func postBody(authorizationCode: String) -> String {
    let grantType = "authorization_code"
    let redirectURL = "https://com.appcoda.linkedin.oauth/oauth"
    return [
        "grant_type":grantType,
        "code":authorizationCode,
        "redirect_uri":redirectURL.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed),
        "client_id":linkedInKey,
        "client_secret":linkedInSecret
    ].enumerated().compactMap {
        if let valueForKey = .value {
            return .key + "=" + valueForKey
        }
        return nil
    }.joined(separator: "&")
}

现在函数 requestForAccessToken(authorizationCode:) 会更短:

func requestForAccessToken(authorizationCode: String) {
    if var urlComponents = URLComponents(string: "https://com.appcoda.linkedin.oauth") {
        urlComponents.path = "/oauth"
        if let urlComponentsURL = urlComponents.url {
            var request = URLRequest(url: urlComponentsURL)
            request.httpMethod = "POST"
            request.httpBody = self.postBody(authorizationCode: authorizationCode).data(using: .utf8)
            request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
            let session = URLSession(configuration: URLSessionConfiguration.default)
            let task: URLSessionDataTask = session.dataTask(with: request) { (data, response, error) in

            }
            task.resume()
        }
    }
}