【问题标题】:Yahoo Weather API in swift Extra argument in oauth requestoauth 请求中的快速额外参数中的 Yahoo Weather API
【发布时间】:2020-05-03 04:00:33
【问题描述】:

我正在尝试将 Yahoo API 服务集成到我的 IOS 应用程序 (https://developer.yahoo.com/weather/documentation.html#oauth-swift) 中。我对 android 没有任何问题,但现在我遇到了 swift 和 Xcode11 的编译器问题。 我添加了 Oauth pod:https://cocoapods.org/pods/OAuthSwift,以及文档中的代码:

import Foundation
/*
See https://github.com/OAuthSwift/OAuthSwift for information on
including this OAuth library in your project.
*/
import OAuthSwift

enum YahooWeatherAPIResponseType:String {
    case json = "json"
    case xml = "xml"
}

enum YahooWeatherAPIUnitType:String {
    case imperial = "f"
    case metric = "c"
}

fileprivate struct YahooWeatherAPIClientCredentials {
    var appId = ""
    var clientId = ""
    var clientSecret = ""
}

class YahooWeatherAPI {
    // Configure the following with your values.
    private let credentials = YahooWeatherAPIClientCredentials(appId: "-your-app-id-", clientId: "-your-client-id-", clientSecret: "-your-client-secret-")

    private let url:String = "https://weather-ydn-yql.media.yahoo.com/forecastrss"
    private let oauth:OAuth1Swift?

    public static let shared = YahooWeatherAPI()

    private init() {
        self.oauth = OAuth1Swift(consumerKey: self.credentials.clientId, consumerSecret: self.credentials.clientSecret)
    }

    private var headers:[String:String] {
        return [
            "X-Yahoo-App-Id": self.credentials.appId
        ]
    }

    /// Requests weather data by location name.
    ///
    /// - Parameters:
    ///   - location: the name of the location, i.e. sunnyvale,ca
    ///   - failure: failure callback
    ///   - success: success callback
    ///   - responseFormat: .xml or .json. default is .json.
    ///   - unit: metric or imperial units. default = .imperial

    public func weather(location:String, failure: @escaping (_ error: OAuthSwiftError) -> Void, success: @escaping (_ response: OAuthSwiftResponse) -> Void, responseFormat:YahooWeatherAPIResponseType = .json, unit:YahooWeatherAPIUnitType = .imperial) {
        self.makeRequest(parameters: ["location":location, "format":responseFormat.rawValue, "u":unit.rawValue], failure: failure, success: success)
    }


    /// Requests weather data by woeid (Where on Earth ID)
    ///
    /// - Parameters:
    ///   - woeid: The location's woeid
    ///   - failure: failure callback
    ///   - success: success callback
    ///   - responseFormat: .xml or .json. default is .json.
    ///   - unit: metric or imperial units. default = .imperial

    public func weather(woeid:String, failure: @escaping (_ error: OAuthSwiftError) -> Void, success: @escaping (_ response: OAuthSwiftResponse) -> Void, responseFormat:YahooWeatherAPIResponseType = .json, unit:YahooWeatherAPIUnitType = .imperial) {
        self.makeRequest(parameters: ["woeid":woeid, "format":responseFormat.rawValue, "u":unit.rawValue], failure: failure, success: success)
    }


    /// Requests weather data by latitude and longitude
    ///
    /// - Parameters:
    ///   - lat: latitude
    ///   - lon: longiture
    ///   - failure: failure callback
    ///   - success: success callback
    ///   - responseFormat: .xml or .json. default is .json.
    ///   - unit: metric or imperial units. default = .imperial
    public func weather(lat:String, lon:String, failure: @escaping (_ error: OAuthSwiftError) -> Void, success: @escaping (_ response: OAuthSwiftResponse) -> Void, responseFormat:YahooWeatherAPIResponseType = .json, unit:YahooWeatherAPIUnitType = .imperial) {
        self.makeRequest(parameters: ["lat":lat, "lon":lon, "format":responseFormat.rawValue, "u":unit.rawValue], failure: failure, success: success)
    }


    /// Performs the API request with the OAuthSwift client
    ///
    /// - Parameters:
    ///   - parameters: Any URL parameters to pass to the endpoint.
    ///   - failure: failure callback
    ///   - success: success callback
    private func makeRequest(parameters:[String:String], failure: @escaping (_ error: OAuthSwiftError) -> Void, success: @escaping (_ response: OAuthSwiftResponse) -> Void) {
        self.oauth?.client.request(self.url, method: .GET, parameters: parameters, headers: self.headers, body: nil, checkTokenExpiration: true, success: success, failure: failure)
    }

}

但我在最后一个 makerequest 函数中收到编译器错误“额外参数”失败“(见附件)。

  private func makeRequest(parameters:[String:String], failure: @escaping (_ error: OAuthSwiftError) -> Void, success: @escaping (_ response: OAuthSwiftResponse) -> Void) {
        self.oauth?.client.request(self.url, method: .GET, parameters: parameters, headers: self.headers, body: nil, checkTokenExpiration: true, success: success, failure: **failure**)
    }

[编译器错误][1]

有人对 Oauth 和此类问题有经验吗?有人可以帮帮我吗?

在此先感谢

这就是应该调用 Yahooweather Oauth 请求的方式(感谢jawadAli):

  public func weather(lat:String, lon:String, responseFormat:YahooWeatherAPIResponseType = .json, unit:YahooWeatherAPIUnitType = .imperial,completion: OAuthSwiftHTTPRequest.CompletionHandler?) {

         self.makeRequest(parameters: ["lat":lat, "lon":lon, "format":responseFormat.rawValue, "u":unit.rawValue], completion: completion)
    }

    private func makeRequest(parameters:[String:String], completion: OAuthSwiftHTTPRequest.CompletionHandler?) {

        self.oauth?.client.request(self.url, method: .GET, parameters: parameters, headers: self.headers, body: nil, checkTokenExpiration: true, completionHandler: completion)}

【问题讨论】:

    标签: ios swift arguments yahoo weather


    【解决方案1】:

    使用OAuth2Swift函数

    self.client.request(accessTokenUrl, method: .POST, parameters: parameters, headers: finalHeaders, checkTokenExpiration: false, completionHandler: completionHandler)
    

    Client Request的实际参数是

    func request(_ url: URLConvertible, method: OAuthSwiftHTTPRequest.Method, parameters: OAuthSwift.Parameters = [:], headers: OAuthSwift.Headers? = nil, body: Data? = nil, checkTokenExpiration: Bool = true, completionHandler completion: OAuthSwiftHTTPRequest.CompletionHandler?) -> OAuthSwiftRequestHandle?
    

    它采用完成处理程序而不是成功失败

    希望它能解决你的问题

    查看此代码...您需要单独发送转义完成处理程序而不是成功或失败

    fileprivate func requestOAuthAccessToken(withParameters parameters: OAuthSwift.Parameters, headers: OAuthSwift.Headers? = nil, completionHandler completion: @escaping TokenCompletionHandler) -> OAuthSwiftRequestHandle? {
    
            let completionHandler: OAuthSwiftHTTPRequest.CompletionHandler = { [weak self] result in
                guard let this = self else {
                    OAuthSwift.retainError(completion)
                    return
                }
                switch result {
                case .success(let response):
                    let responseJSON: Any? = try? response.jsonObject(options: .mutableContainers)
    
                    let responseParameters: OAuthSwift.Parameters
    
                    if let jsonDico = responseJSON as? [String: Any] {
                        responseParameters = jsonDico
                    } else {
                        responseParameters = response.string?.parametersFromQueryString ?? [:]
                    }
    
                    guard let accessToken = responseParameters["access_token"] as? String else {
                        let message = NSLocalizedString("Could not get Access Token", comment: "Due to an error in the OAuth2 process, we couldn't get a valid token.")
                        completion(.failure(.serverError(message: message)))
                        return
                    }
    
                    if let refreshToken = responseParameters["refresh_token"] as? String {
                        this.client.credential.oauthRefreshToken = refreshToken.safeStringByRemovingPercentEncoding
                    }
    
                    if let expiresIn = responseParameters["expires_in"] as? String, let offset = Double(expiresIn) {
                        this.client.credential.oauthTokenExpiresAt = Date(timeInterval: offset, since: Date())
                    } else if let expiresIn = responseParameters["expires_in"] as? Double {
                        this.client.credential.oauthTokenExpiresAt = Date(timeInterval: expiresIn, since: Date())
                    }
    
                    this.client.credential.oauthToken = accessToken.safeStringByRemovingPercentEncoding
                    completion(.success((this.client.credential, response, responseParameters)))
                case .failure(let error):
                    completion(.failure(error))
                }
            }
    

    把你的方法定义改成

    private func makeRequest(parameters:[String:String], completion: @escaping TokenCompletionHandler) -> OAuthSwiftRequestHandle?)
    

    此 TokenCompletionHandler 是一个 ResultType ....您可以添加失败或成功案例的切换...如果您需要进一步帮助,请告诉我

    【讨论】:

    • 您好,感谢您的回答。我目前不在家。这个功能是嵌入的吗?如果没有,你能给我链接代码/pod吗?
    • 这个函数在OAuthSwiftClient我使用的是从你提供的链接下载的同一个Pod
    • 感谢我的努力 =)
    • 暂未解决,感谢支持,详情见
    • 先生,我只是不明白,而且我在尝试编写代码而不从编译器收到错误时感到头疼。我对 swift 不是很熟悉,也不明白为什么让 oauth 请求工作如此困难。如果您将上面的代码无误地发送给我,我将不胜感激。如果你不这样做,我会理解的。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-04
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 2019-04-16
    相关资源
    最近更新 更多