如何从swift的viewdidload函数中的GET请求函数中数组

问题描述:

我是新手,所以我的代码可能会出现很多错误,但是我要实现的目标是将GET请求发送到函数内部带有参数的服务器.我想在Viewdidload和其他函数中使用从服务器收到的数组,但似乎无法找到一种存储数组的方法,因此我可以使用它.在我的函数中已填充,但在我的函数中为空

I'm very new to swift, so I will probably have a lot of faults in my code but what I'm trying to achieve is send a GET request to a server with paramters inside a function. I want to use the array I receive from the server in my viewdidload and in other functions but cant seem to find a way to store the array so i can use it. in my function it is filled, but out of my function it is empty

var scenarioArray: Array<Any> = []


let idPersoon = UserDefaults.standard.object(forKey: "idPersoon") as! String

override func viewDidLoad() {
super.viewDidLoad()
ScenarioArray()
print(scenarioArray)
print(self.scenarioArray)
}
func ScenarioArray()  {

    var request = URLRequest(url: URL(string: "http://dtsl.ehb.be/app&web/ios_php/getAllScenariosByPersoon.php?persoonID="+idPersoon)!)
    request.httpMethod = "GET"
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {                                                 // check for fundamental networking error
            print("error=\(error)")
            return
        }
        do {
            if let jsonResult = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {
                self.scenarioArray = (jsonResult["Scenarios"] as! NSArray) as! Array<Any>
                print("ASynchronous\(self.scenarioArray)")

            }
        } catch let error as NSError {
            print(error.localizedDescription)
            }



    }
    task.resume()
}

您的问题"是您试图从服务器获取数据,这意味着您正在进行网络呼叫.

Your "problem" is that you are trying to GET data from a server, meaning that you are doing a network call.

现在...您不知道启动网络通话所需的时间 时间,如果您的网络良好,则通话速度可能很快,但是如果使用3G,网络可能需要一段时间.

Now...you don't know how long that network call will take when you launch it, if you are on a good network then it might be fast, but if you are on 3G network it might take a while.

如果对服务器的调用是同步完成的,那么结果将是每次您尝试获取数据时,您的代码都将专注于执行此操作,这意味着其他任何操作都不会继续进行...即不是你想要的:)

If the call to your server was done synchronously, the result would be that each and every time you'd try to fetch data your code would focus on doing just that, meaning that nothing else would go on... that is not what you want :)

相反,当您使用URLSession并调用task.resume()时,该方法是异步执行的,这意味着它在后台的另一个线程上开始,它将在该线程上获取数据.

Instead, when you use URLSession, and call task.resume() that method is executed asynchronously, meaning that it starts on another thread in the background where it will fetch data.

同时,您的主线程可以*处理UI渲染等.在不久的将来,您的网络通话将结束,您现在拥有有效的数据,并且必须告知需要知道的人.

In the meantime, your main thread is free to handle UI rendering and so on. At some point in the near future your network call finishes and you now have valid data and must inform whoever needs to know.

因此,当您调用 dataTask(with:completeHandler:),您实际上所说的是类似以下内容的内容:

So when you do a call to dataTask(with: completionHandler:), what you are actually saying is something along the lines of:

嘿...请在后台获取此数据,当您完成操作后,我想使用您告诉我的参数执行在completionHandler中传递给您的代码.

"hey...go fetch this data in the background please, and when you're done, I'd like to execute the code I've passed you here in the completionHandler with the parameters you tell me about".

希望有点道理:)

现在...您有此代码:

Now...you have this code:

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    guard let data = data, error == nil else {                                                 // check for fundamental networking error
        print("error=\(error)")
        return
    }
    do {
        if let jsonResult = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {
            self.scenarioArray = (jsonResult["Scenarios"] as! NSArray) as! Array<Any>
            print("ASynchronous\(self.scenarioArray)")

        }
    } catch let error as NSError {
        print(error.localizedDescription)
    }
}

函数调用({ data, response, error in...)的最后一部分是completionHandler,它不会立即执行.直到数据检索完成才执行.

That last part of the function call ({ data, response, error in...) is the completionHandler, which is not executed straight away. It is not executed until the retrieval of data has completed.

然后因此当您在viewDidLoad中调用ScenarioArray()函数时,将发生的情况是异步调用以获取数据将在后台启动,而viewDidLoad将在后台启动.继续执行操作,这意味着当您说:

And therefore when you do a call to your ScenarioArray() function in viewDidLoad, what will happen is that the asynchronous call to fetch data will start in the background and your viewDidLoad will continue what it is doing, meaning that when you say:

print(scenarioArray)
print(self.scenarioArray)

那么您就不能期望scenarioArray会被填充,因为您的task忙于在后台获取数据.

then you can not expect scenarioArray to be populated yet as your task is busy fetching that data in the background.

所以...正如@vadian所说,您需要做的就是在获取数据后更新 UI ,也就是说,在completionHandler中.

So...what you need to do, as @vadian says, is to update your UI once the data has been fetched, meaning, in the completionHandler.

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    guard let data = data, error == nil else {                                                 // check for fundamental networking error
        print("error=\(error)")
        return
    }
    do {
        if let jsonResult = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {
            self.scenarioArray = (jsonResult["Scenarios"] as! NSArray) as! Array<Any>
            print("ASynchronous\(self.scenarioArray)")
            //Now you have data, reload the UI with the right scenarioArray
        }
    } catch let error as NSError {
        print(error.localizedDescription)
    }
}

希望并能为您提供帮助.

Hope that makes sense and helps you.