在 iOS 上使用 swift 使用 REST API 时出错
Posted
技术标签:
【中文标题】在 iOS 上使用 swift 使用 REST API 时出错【英文标题】:Error consuming REST API using swift on iOS 【发布时间】:2016-03-03 19:51:04 【问题描述】:我是 ios 开发新手,我一直在学习本教程:https://grokswift.com/simple-rest-with-swift/,但我不知道为什么下面的代码总是返回“占位符”,而且我在控制台的输出中看不到错误:
import Foundation
class Resolver
func doSomething() -> String
var result = "the placeholder"
print("inside doSomething")
let postEndpoint: String = "http://jsonplaceholder.typicode.com/posts/1"
guard let url = NSURL(string: postEndpoint) else
print("Error: cannot create URL")
return "error here"
let urlRequest = NSURLRequest(URL: url)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
print("another thing")
let task = session.dataTaskWithRequest(urlRequest, completionHandler:
(data, response, error) in
guard let responseData = data else
print("Error: did not receive data")
return
//return "error here"
print("hereeeeeee ############")
guard error == nil else
print("error calling GET on /posts/1")
print(error)
return
//return "error here"
// parse the result as JSON, since that's what the API provides
let post: NSDictionary
do
post = try NSJSONSerialization.JSONObjectWithData(responseData,
options: []) as! NSDictionary
catch
print("error trying to convert data to JSON")
return
//return "error here"
// now we have the post, let's just print it to prove we can access it
print("The post is: " + post.description)
result = post.description
// the post object is a dictionary
// so we just access the title using the "title" key
// so check for a title and print it if we have one
if let postTitle = post["title"] as? String
print("The title is: " + postTitle)
)
task.resume()
return result
这是我的 info.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string></string>
<key>CFBundleExecutable</key>
<string></string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>CFBundleName</key>
<string></string>
<key>CFBundleDisplayName</key>
<string></string>
<key>CFBundleVersion</key>
<string></string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>httpbin.org</key>
<dict>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>jsonplaceholder.typicode.com </key>
<dict>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>CFBundleShortVersionString</key>
<string></string>
<key>CFBundleGetInfoString</key>
<string></string>
</dict>
</plist>
当我运行测试时,我看到了这个输出:
Test Suite 'RestTest' started at 2016-03-03 15:38:49.364
Test Case '-[FoodTrackerTests.RestTest testResolver]' started.
inside doSomething
another thing
// I want to see the result: the placeholder
Test Case '-[FoodTrackerTests.RestTest testResolver]' passed (0.061 seconds).
Test Suite 'RestTest' passed at 2016-03-03 15:38:49.425.
Executed 1 test, with 0 failures (0 unexpected) in 0.061 (0.062) seconds
Test Suite 'Selected tests' passed at 2016-03-03 15:38:49.426.
Executed 1 test, with 0 failures (0 unexpected) in 0.061 (0.063) seconds
为什么结果变量不包含 post.description 值?
【问题讨论】:
你试过在task
里面添加断点吗?为什么它永远不会被调用?你的错误也没有抛出。也许这是因为您正在运行测试并且测试在异步 API 调用之前完成?
我尝试在操场上运行您的代码,但它不会像您发现的那样产生输出。但是,当我在真机上运行它时,它立即运行良好。
@remus 你是对的。测试总是在 http 调用完成之前完成。我不知道您是否必须发布答案才能将其标记为已接受,或者我是否必须自己这样做。
【参考方案1】:
正如 cmets 中所建议的,在返回 HTTP 调用之前测试似乎已经完成(因为 HTTP 请求是异步的),因此在测试运行结束之前您看不到 API 调用的结果。
查看XCAsyncTestCase 并将您的测试设置为等待异步回调。
【讨论】:
【参考方案2】:doSomething()
方法在异步调用完成之前返回"the placeholder"
值。这就是你看到它的原因。
【讨论】:
以上是关于在 iOS 上使用 swift 使用 REST API 时出错的主要内容,如果未能解决你的问题,请参考以下文章
Swift iOS 应用程序到 REST PHP API - 身份验证的最佳实践是啥?