快速开展学校项目(自己学习这种语言),我需要使用一些Headerfields发出 Get方法HTTP请求,并将其放入json对象(这部分工作良好)。
>此后,我想显示JsonObjects从新到旧的最后5个部分,因此我决定将它们放在Strings表中,并能够将这些Strings(按我的需要)分配给几个UILabel。文本。
当我第一次按下按钮(分配给@IBAction)时,标签保持不变,但表已满(在} catch {之前使用print(self.tableau)进行了尝试) )
变量初始化:
var tableau: [String] = []
struct Donnee: Decodable
{
let device_id: String
let raw: String
let receivedString: String
let time: String
init(json : [String: Any]){
device_id = json["device_id"] as? String ?? ""
raw = json["raw"] as? String ?? ""
receivedString = json["receivedString"] as? String ?? ""
time = json["time"] as? String ?? ""
}
}
代码制作问题:
@IBAction func sendButtonTapped(_ sender: AnyObject) {
// Send HTTP GET Request
// Define server side script URL
let scriptUrl = "https://lora-thomas-slave.data.thethingsnetwork.org/api/v2/query?last=7d"
// Create NSURL Ibject
let myUrl = NSURL(string: scriptUrl);
// Creaste URL Request
let request = NSMutableURLRequest(url:myUrl! as URL);
// Set request HTTP method to GET. It could be POST as well
request.httpMethod = "GET"
// Or it could be a single Authorization Token value
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("key ttn-account-v2.*************", forHTTPHeaderField: "Authorization")
// Excute HTTP Request
URLSession.shared.dataTask(with: request as URLRequest) {(data, response, error) in
do{
// Try to assign Json Lora data into an array of Structured data
let donne = try JSONDecoder().decode([Donnee].self, from: data!)
// For each data, print the received string
let compt: Int = donne.count //compt = number of json objects
var j : Int = 0
var chaine: String = " "
var x : Int = 0
for i in donne{
if (j > (compt-6)){
chaine = i.time.split(separator: "T")[0] + " " + i.time.split(separator: "T")[1].split(separator: ".")[0] + " : " + i.receivedString
self.tableau.append(chaine)
x += 1
}
j += 1
}
}catch{
print("error !")
}
}.resume()
//This code is executing the second time that i pushed the button
//**********************//
if(self.tableau.count != 0){
self.labelMess0.text = self.tableau[4]
self.labelMess1.text = self.tableau[3]
self.labelMess2.text = self.tableau[2]
self.labelMess3.text = self.tableau[1]
self.labelMess4.text = self.tableau[0]
}
//**********************//
}
我已经尝试在捕获之前将代码放在// ******** //之间,但是我收到一个错误消息,告诉我只有主线程才能修改UILabel.text ^^(UILabel.text必须仅在主线程中使用)
有人知道这种问题,也许知道解决方法? 感谢您的帮助
编辑
第一件事是,标签第一次更改,但是当我再次按下按钮时仍然不更新标签。 (其目的是能够通过互联网记录字符串的历史记录,因此,当将其他信息分配给Table tableau [4]并进行其他更改时,(新的Tableau [3]是最后一个Tableau [4 ])UIlabel.text似乎没有更新)Table Tableau []的供稿很好:)
答案 0 :(得分:1)
URLSession.shared.dataTask(
在后台线程中运行,因此任何ui更新都应嵌入其中
DispatchQueue.main.async {
if self.tableau.count >= 5 { // avoid crashes
self.labelMess0.text = self.tableau[4]
self.labelMess1.text = self.tableau[3]
self.labelMess2.text = self.tableau[2]
self.labelMess3.text = self.tableau[1]
self.labelMess4.text = self.tableau[0]
}
}
答案 1 :(得分:1)
您在线程方面遇到问题
@IBAction func sendButtonTapped(_ sender: AnyObject) {
[...]
// Object that holds http request information
let request = NSMutableURLRequest(url:myUrl! as URL)
// set cookies, body, headers, whatever
[...]
[1]
// now create download handler
let downloadHandler = URLSession.shared.dataTask(
with: request as URLRequest
) {
[3]
[some function to be executed when download finishes]
}
[2]
// start download
downloadHandler.resume()
// use of variable that isn't initialised yet!
if(self.tableau.count != 0){
}
}
流程如下:
(请注意,您无法在后台线程上编辑UI元素)
因此您的代码应如下:
@IBAction func sendButtonTapped(_ sender: AnyObject) {
// Send HTTP GET Request
// Define server side script URL
let scriptUrl = "https://lora-thomas-slave.data.thethingsnetwork.org/api/v2/query?last=7d"
// Create NSURL Ibject
let myUrl = NSURL(string: scriptUrl);
// Creaste URL Request
let request = NSMutableURLRequest(url:myUrl! as URL);
// Set request HTTP method to GET. It could be POST as well
request.httpMethod = "GET"
// Or it could be a single Authorization Token value
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("key ttn-account-v2.*************", forHTTPHeaderField: "Authorization")
// Excute HTTP Request
URLSession.shared.dataTask(with: request as URLRequest) {(data, response, error) in
do{
// Try to assign Json Lora data into an array of Structured data
let donne = try JSONDecoder().decode([Donnee].self, from: data!)
// For each data, print the received string
let compt: Int = donne.count //compt = number of json objects
var j : Int = 0
var chaine: String = " "
var x : Int = 0
for i in donne{
if (j > (compt-6)){
chaine = i.time.split(separator: "T")[0] + " " + i.time.split(separator: "T")[1].split(separator: ".")[0] + " : " + i.receivedString
self.tableau.append(chaine)
x += 1
}
j += 1
}
DispatchQueue.main.async {
if(self.tableau.count != 0){
self.labelMess0.text = self.tableau[4]
self.labelMess1.text = self.tableau[3]
self.labelMess2.text = self.tableau[2]
self.labelMess3.text = self.tableau[1]
self.labelMess4.text = self.tableau[0]
}
}
}catch{
print("error !")
}
}.resume()
}
答案 2 :(得分:1)
就像我在评论中提到的那样,您需要使用
在主线程上进行UI更新DispatchQueue.main.async {
self.labelMess0.text = self.tableau[4]
self.labelMess1.text = self.tableau[3]
self.labelMess2.text = self.tableau[2]
self.labelMess3.text = self.tableau[1]
self.labelMess4.text = self.tableau[0]
}
您的第二个问题是,当再次按下按钮时,新结果将附加到数组中,这意味着它将位于5-9位置,因此您需要先清除数组,self.tableau.removeAll()
直接在sendButtonTapped
中进行操作,或者最好在闭包中首先进行操作,这样如果请求失败,旧值就不会消失。