REST API 调用 Swift 5.2

REST API call with Swift 5.2

我编写了一个简单的 python 脚本来从 Finnhub.io 获取股票的股息数据,此代码有效并在下面 post 编辑。

#!/usr/bin/env python
import requests

resp = requests.get('https://finnhub.io/api/v1/stock/dividend?symbol=AAPL&from=2010-01-01&to=2020-12-31&token=xxx')
if resp.status_code != 200:
    # This means something went wrong.
    raise ApiError('GET /api/v1/stock/dividend?symbol=AAPL&from=2010-01-01&to=2020-12-31&token=xxx {}'.format(resp.status_code))
else:
    for dividend_item in resp.json():
        print('{} {} {}'.format(dividend_item['date'], dividend_item['symbol'], dividend_item['amount']))

运行 python 脚本的结果如下所示:

2020-02-07 AAPL 0.77
2019-11-07 AAPL 0.77
2019-08-09 AAPL 0.77
2019-05-10 AAPL 0.77
2019-02-08 AAPL 0.73
2018-11-08 AAPL 0.73
2018-08-10 AAPL 0.73
2018-05-11 AAPL 0.73
2018-02-09 AAPL 0.63
2017-11-10 AAPL 0.63
2017-08-10 AAPL 0.63
2017-05-11 AAPL 0.63
2017-02-09 AAPL 0.57
2016-11-03 AAPL 0.57
2016-08-04 AAPL 0.57
2016-05-05 AAPL 0.57
2016-02-04 AAPL 0.52
2015-11-05 AAPL 0.52
2015-08-06 AAPL 0.52
2015-05-07 AAPL 0.52
2015-02-05 AAPL 0.47
2014-11-06 AAPL 0.47
2014-08-07 AAPL 0.47
2014-05-08 AAPL 0.47
2014-02-06 AAPL 0.43571
2013-11-06 AAPL 0.43571
2013-08-08 AAPL 0.43571
2013-05-09 AAPL 0.43571
2013-02-07 AAPL 0.37857
2012-11-07 AAPL 0.37857
2012-08-09 AAPL 0.37857

让我头疼的是在 iOS 13 上将其转换为 Swift 5.2。我在 Whosebug (Make REST API call in Swift) 上找到了一个很好的 post 并调整了代码到我下面的 Swift 代码。

    func getDividendData() {
        let params = ["username":"john", "password":"123456"] as Dictionary<String, String>

        var request = URLRequest(url: URL(string: "https://finnhub.io/api/v1/stock/dividend?symbol=AAPL&from=2010-01-01&to=2020-12-31&token=xxx")!)
        request.httpMethod = "GET"
        request.httpBody = try? JSONSerialization.data(withJSONObject: params, options: [])
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")

        let session = URLSession.shared
        let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in
            print(response!)
            do {
                let json = try JSONSerialization.jsonObject(with: data!) as! Dictionary<String, AnyObject>
                print(json)
            } catch {
                print("error")
            }
        })

        task.resume()
    }

当我调用 getDividendData() 方法时,出现以下错误。由于我在 Swift 编程方面不是很有经验,但我希望有人能给我提示。

2020-04-21 22:39:27.963666+0200 RESTtest[15836:1085147] GET method must not have a body
2020-04-21 22:39:27.967193+0200 RESTtest[15836:1085147] Task <C919CF75-FB01-4FF5-8CC8-646B1CA1FB5D>.<1> finished with error [-1103] Error Domain=NSURLErrorDomain Code=-1103 "resource exceeds maximum size" UserInfo={NSUnderlyingError=0x600002953240 {Error Domain=kCFErrorDomainCFNetwork Code=-1103 "(null)"}, NSErrorFailingURLStringKey=https://finnhub.io/api/v1/stock/dividend?symbol=AAPL&from=2010-01-01&to=2020-12-31&token=xxx0, NSErrorFailingURLKey=https://finnhub.io/api/v1/stock/dividend?symbol=AAPL&from=2010-01-01&to=2020-12-31&token=xxx, NSLocalizedDescription=resource exceeds maximum size}
Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /Users/joe/Desktop/RESTtest/RESTtest/ViewController.swift, line 27
2020-04-21 22:39:27.967483+0200 RESTtest[15836:1085147] Fatal error: Unexpectedly found nil while unwrapping an Optional value: file /Users/joe/Desktop/RESTtest/RESTtest/ViewController.swift, line 27
(lldb) 

P.S.: 出于隐私原因,我用 xxx 替换了令牌。

如错误所述:

GET method must not have a body

所以错误原因是行:

request.httpBody

您必须改为添加 URL 参数(查询项)。

let url = URL(string: "https:// Your url path")!
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
let queryItems: [URLQueryItem] = params.map { parameter in
    URLQueryItem(name: parameter.key, value: parameter.value)
}

components.queryItems = queryItems

var request = URLRequest(url: components.url!)
// ...