在 iOS Swift 中使用委托和协议 return 来自 dataTaskWithRequest 的数据
Using Delegated and Protocols to return data from dataTaskWithRequest in iOS Swift
我有一个调用 API 的框架,其中 returns 调用 JSON 返回给我。问题是我的 SDK 中有一个函数,它使用 NSURLSession 并调用 DataTaskWithRequest 来获取数据。问题是我的函数 returns 即使在正确获取数据之前的值。我尝试将 Completion Handler 与 DataTaskWithRequest 一起使用,目前使用 while 循环等待接收数据。还有其他可能的方法吗
代码
public func getDetails() -> AnyObject {
if Reachability.isConnectedToNetwork()
{
received = false
let baseUrl = "API_URL Here"
let url = NSURL(string: baseUrl)
let request = NSURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
print("Starting the connection")
let task = session.dataTaskWithRequest(request, completionHandler : {
(data, response, error ) in
//Proper JSON Form
do
{
self.JSON = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
}
catch
{
print("Error")
return
}
self.received = true
})
task.resume()
print("Going through the loop")
while(!received)
{
print("Searching")
}
print(JSON)
return JSON
}
else
{
let alert = UIAlertView(title: "No Internet Connection", message: "Make sure your device is connected to the internet.", delegate: nil, cancelButtonTitle: "OK")
alert.show()
return 0
}
}
是的,使用另一个线程来监视进程并让它通过您的协议发送消息。
newQueue = NSOperationQueue()
let operation2 = NSBlockOperation(block: {
})
operation2.completionBlock = {
print("Operation 2 completed")
}
let operation1 = NSBlockOperation(block: {
})
operation1.completionBlock = {
self.newQueue.addOperation(operation2)
}
operation1.qualityOfService = .UserInitiated
newQueue.addOperation(operation1)
}
这是代码的概要。简而言之,您使用块 1 启动您的会话,并在完成时使用块 2 启动您的下载验证。 block1 在完成时触发 block2 [几乎像你说的那样],但 block 2 在下载 block 1 中完成的数据结构之前不会触发。
你的问题是你试图将异步的东西变成同步的东西。用伪代码总结一下,您正在这样做:-
let myData = getDetails(blah)
doSomeAction(myData)
接近它的方法是使用完成块作为指标本身,并使一切异步。
此代码未经测试
public typealias CompletionHandler = (success: Bool, message: String, json: JSON?, error: NSError?) -> Void
func getDetailsAsync(completion: CompletionHandler) {
if Reachability.isConnectedToNetwork()
{
received = false
let baseUrl = "API_URL Here"
let url = NSURL(string: baseUrl)
let request = NSURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
print("Starting the connection")
let task = session.dataTaskWithRequest(request, completionHandler : {
(data, response, error ) in
//Proper JSON Form
if error != nil {
completion(false, "error", nil, error)
}
else {
do
{
self.JSON = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
completion(true, "OK", self.JSON, nil)
}
catch
{
print("Error")
completion(false, "JSON parsing failed", nil, nil)
}
}
})
task.resume()
}
else {
completion(false, "No network", nil, nil)
}
}
这样称呼它:
getDetailsAsync() {
(success, message, json, error) in
if success == true {
print(json)
}
else {
// Do your alert here
print(message)
print(error)
}
}
回答可能会有帮助。
我有一个调用 API 的框架,其中 returns 调用 JSON 返回给我。问题是我的 SDK 中有一个函数,它使用 NSURLSession 并调用 DataTaskWithRequest 来获取数据。问题是我的函数 returns 即使在正确获取数据之前的值。我尝试将 Completion Handler 与 DataTaskWithRequest 一起使用,目前使用 while 循环等待接收数据。还有其他可能的方法吗
代码
public func getDetails() -> AnyObject {
if Reachability.isConnectedToNetwork()
{
received = false
let baseUrl = "API_URL Here"
let url = NSURL(string: baseUrl)
let request = NSURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
print("Starting the connection")
let task = session.dataTaskWithRequest(request, completionHandler : {
(data, response, error ) in
//Proper JSON Form
do
{
self.JSON = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
}
catch
{
print("Error")
return
}
self.received = true
})
task.resume()
print("Going through the loop")
while(!received)
{
print("Searching")
}
print(JSON)
return JSON
}
else
{
let alert = UIAlertView(title: "No Internet Connection", message: "Make sure your device is connected to the internet.", delegate: nil, cancelButtonTitle: "OK")
alert.show()
return 0
}
}
是的,使用另一个线程来监视进程并让它通过您的协议发送消息。
newQueue = NSOperationQueue()
let operation2 = NSBlockOperation(block: {
})
operation2.completionBlock = {
print("Operation 2 completed")
}
let operation1 = NSBlockOperation(block: {
})
operation1.completionBlock = {
self.newQueue.addOperation(operation2)
}
operation1.qualityOfService = .UserInitiated
newQueue.addOperation(operation1)
}
这是代码的概要。简而言之,您使用块 1 启动您的会话,并在完成时使用块 2 启动您的下载验证。 block1 在完成时触发 block2 [几乎像你说的那样],但 block 2 在下载 block 1 中完成的数据结构之前不会触发。
你的问题是你试图将异步的东西变成同步的东西。用伪代码总结一下,您正在这样做:-
let myData = getDetails(blah)
doSomeAction(myData)
接近它的方法是使用完成块作为指标本身,并使一切异步。 此代码未经测试
public typealias CompletionHandler = (success: Bool, message: String, json: JSON?, error: NSError?) -> Void
func getDetailsAsync(completion: CompletionHandler) {
if Reachability.isConnectedToNetwork()
{
received = false
let baseUrl = "API_URL Here"
let url = NSURL(string: baseUrl)
let request = NSURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
print("Starting the connection")
let task = session.dataTaskWithRequest(request, completionHandler : {
(data, response, error ) in
//Proper JSON Form
if error != nil {
completion(false, "error", nil, error)
}
else {
do
{
self.JSON = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
completion(true, "OK", self.JSON, nil)
}
catch
{
print("Error")
completion(false, "JSON parsing failed", nil, nil)
}
}
})
task.resume()
}
else {
completion(false, "No network", nil, nil)
}
}
这样称呼它:
getDetailsAsync() {
(success, message, json, error) in
if success == true {
print(json)
}
else {
// Do your alert here
print(message)
print(error)
}
}