2017-02-16 5 views
-1

У меня есть эта функция, восстанавливающая счет игрока из базы данных MySQL. Из других учебных пособий я нашел подход URLSession полезным при отправке данных из приложения, но смогу ли я реально использовать возврат функции в любом месте? Сохранено в поисках чего-то вродеМогу ли я использовать URLSession в функции с возвратом?

task.resume() 
task.end() 
return (rank, name, score) 

?

func downloadLocalScores(_ choice: Int) -> ([String], [String], [String]) { 
    var url: URL 
    let id: String = getUserID("id") 
    if choice == 0 { 
     url = NSURL(string: "myPHPscript.php")! as URL 
    } else { 
     url = NSURL(string: "myPHPscript2.php")! as URL 
    } 
    let request = NSMutableURLRequest(url: url) 
    request.httpMethod = "POST" 
    let postString = "id=\(id)" 
    request.httpBody = postString.data(using: String.Encoding.utf8) 
    var name: [String] = [] 
    var score: [String] = [] 
    var rank: [String] = [] 
    if Reachability().isInternetAvailable() == true { 
     let task = URLSession.shared.dataTask(with: request as URLRequest) { 
      data, response, error in 
      if error == nil { 
       let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) 
       let variables = try! JSONSerialization.jsonObject(with: data! as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSArray 
       for i in 0..<variables.count { 
        let level = variables[i] as! [String:AnyObject] 
        name.append(level["name"] as! String) 
        score.append(level["score"] as! String) 
        rank.append(level["rank"] as! String) 
       } 
      } else { 
       print(error) 
      } 
     } 
     task.resume() 
     return (rank, name, score) 
    } else { 
     return (["NO CONNECTION"], ["0"]) 
    } 
} 

У меня есть еще одна функция, чтобы загрузить результаты, но, будучи просьбой рекордсменов, не нужно принимать какие-либо входные данные из приложения

func downloadScores(_ choice: Int) -> ([String], [String]) { 
var url: URL 
if choice == 0 { 
    url = NSURL(string: "myPHPscript.php")! as URL 
} else { 
    url = NSURL(string: "myPHPscript2.php")! as URL 
} 
let data = NSData(contentsOf: url) 
var variables: NSArray = [] 
if Reachability().isInternetAvailable() == true { 
    variables = try! JSONSerialization.jsonObject(with: data! as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSArray 

    var name: [String] = [] 
    var score: [String] = [] 

    for i in 0..<variables.count { 
     let level = variables[i] as! [String:AnyObject] 
     name.append(level["name"] as! String) 
     score.append(level["score"] as! String) 
    } 
    return (name, score) 
} else { 
    return (["No connection"], [""]) 
} 

}

Я до сих пор не вполне знакомы с другими вариантами отправки данных из моего приложения, так может ли последняя функция быть адаптирована к POST? Попробовали что-то вчера вечером, но застряли в data = NSData, запрашивая URL-адрес типа вместо NSMutableURLRequest, который у меня был.

Следует упомянуть, что я создал глобальные переменные и добавлял внутри первой функции, но результат восстанавливается после их использования, и я не могу найти способ задержки или обновления после их заполнения. Я не против приложения, ожидающего их, поскольку они используются после viewDidLoad().

+0

Это не значит, что вы не можете «вернуть» значение с помощью NSURLSession, это просто, что вы пытаетесь обойти асинхронную систему. Вы можете обойти его, но это не рекомендуется. Просто продолжайте использовать закрытие. Дело не в использовании async 'stuff, должно блокировать текущий поток, и, как правило, это основной, и он блокирует пользовательский интерфейс (довольно уродливый). Кроме того, 'NSData (contentsOf:)' выполняет GET, а не POST. – Larme

+0

Каков ваш вопрос? – alecnash

ответ

0

Вы не можете вернуться, потому что запросы сети происходят асинхронно. Вместо использования возврата используйте закрытие, которое вызывается, когда запрос завершен. Проверьте следующее:

func sendRequest(_ _request:URLRequest, completion:@escaping (_ success:Bool,_ error:Error?, _ _data:[String:AnyObject]?)->Void) -> URLSessionDataTask { 
    let session:URLSession = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: self.queue) 
    let task:URLSessionDataTask = session.dataTask(with: _request) { (_data, _response, _error) in 
     if let resultsDic:[String:AnyObject] = self.parseJSONFromData(retrievedData, withInitalKey: self.getInitialKey()){ 
      completion(true, nil, resultsDic) 
     } else { 
      completion(false, nil, nil) 
     } 
    } 
    task.resume() 
    return task 
} 
0

Я создал небольшой пример, чтобы показать разницу между входным, возврата и завершения асинхронной. Вставьте это на свою площадку и поэкспериментируйте.

Сначала вы увидите «прошедшие» отпечатки.

Вслед за возвращением.

И последнее завершение, когда асинк закончился.

import UIKit 
import PlaygroundSupport 
import Foundation 

func getStuffFromServer(_ passedIn: String, completion: @escaping (_ completion: String)->()) -> String { 

    print(passedIn) 

    PlaygroundPage.current.needsIndefiniteExecution = true 

    URLSession.shared.dataTask(with: URL(string: "http://stackoverflow.com")!) { 
    result in 

     completion("I've completed") 

     PlaygroundPage.current.finishExecution() 

    }.resume() 

    let returnValue = "I'm being returned" 
    print(returnValue) 
    return returnValue 
} 

let returned = getStuffFromServer("I'm passed in", completion: { completion in 
    print(completion) 
})