2017-03-10 77 views
0

我試圖使用JSON從REST API顯示帶有字符串的UILabel,但沒有運氣。我可以將字符串打印到控制檯上,但是嘗試使用UILabel顯示此字符串時,它顯示爲空白。無法使用JSON數據更新UILabel

這是測試代碼,我有工作:

import UIKit 

class List { 
    var title = String() 
} 

class ViewController: UIViewController { 
    override func viewDidLoad() { 
    super.viewDidLoad() 
    let list = List() 
    callAPI() 
    let width = view.bounds.width 
    let height = view.bounds.height 
    let label: UILabel = { 
     let label = UILabel(frame: CGRect(x: 0, y: height/2 - 50, width: width, height: 50)) 
     label.backgroundColor = UIColor.red 
     label.text = title 
    return label 
    }() 
    view.addSubview(label) 
    print("Label Text: \(list.title)") 
    } 
} 

let url = URL(string: "https://jsonplaceholder.typicode.com/todos/") 

func callAPI() { 
    URLSession.shared.dataTask(with: url!, completionHandler: { 
    (data, response, error) in 
    if error != nil { 
     print(error!) 
     return 
    } 
    do { 
     let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSMutableArray 
     let array = json[0] as! [String:Any] 
     let title = array["title"] as! String 
     print("Title: \(title)") 
     let list = List() 
     list.title = title 
    } 
    catch let jsonError { 
     print(jsonError) 
    } 
    }).resume() 
} 
+0

你的'List'類和'list'屬性有什麼用? – rmaddy

+0

代碼'label.text = title'在調用API之前立即運行。您只能在完成處理程序運行期間或之後期待JSON的標題。這就是爲什麼你應該採取rmaddy的建議,並更新該處理程序的用戶界面。 – danh

回答

0

這似乎是要替換這些行:

let list = List() 
list.title = title 

有:

label.text = title 

你的代碼已創建,更新並丟棄List實例,但不會嘗試更新您的實際UILabel

創建並設置標籤後,您還需要將呼叫移至callAPI()

+0

哪個「let list = List()」你指的是? – sMk

+0

在分析JSON數據之後,您只需在一個地方安裝這兩行代碼。 – rmaddy

+0

好吧,但現在我得到這個錯誤...「使用未解析的標識符」標籤「 – sMk

0

在你的ViewController,您創建的List()的實例,但callAPI()創建自己的List()實例,並更新標題屬性,而不是實例在你的ViewController的title屬性。

您可以刪除callAPI()方法,直接將代碼放在您的視圖控制器和直接更新label.text,你可以有callAPI接受UILabel類型的參數和更新,如:

class ViewController: UIViewController { 
    override func viewDidLoad() { 
     super.viewDidLoad() 


     let width = view.bounds.width 
     let height = view.bounds.height 

     let label: UILabel = { 
      let label = UILabel(frame: CGRect(x: 0, y: height/2 - 50, width: width, height: 50)) 
      label.backgroundColor = UIColor.red 
      return label 
     } 

     callAPI(label) 

     view.addSubview(label) 
     print("Label Text: \(list.title)") 
    } 
} 

let url = URL(string: "https://jsonplaceholder.typicode.com/todos/") 

func callAPI(_ label: UILabel) { 
    URLSession.shared.dataTask(with: url!, completionHandler: { 
    (data, response, error) in 
    if error != nil { 
     print(error!) 
     return 
    } 
    do { 
     let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSMutableArray 
     let array = json[0] as! [String:Any] 
     let title = array["title"] as! String 
     print("Title: \(title)") 

     label.text = title 
    } 
    catch let jsonError { 
     print(jsonError) 
    } 
    }).resume() 
} 

,或者你可以有callAPI採取List()的實例作爲參數,並更新title屬性:

class ViewController: UIViewController { 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     let list = List() 
     callAPI(list) 

     let width = view.bounds.width 
     let height = view.bounds.height 

     let label: UILabel = { 
      let label = UILabel(frame: CGRect(x: 0, y: height/2 - 50, width: width, height: 50)) 
      label.backgroundColor = UIColor.red 
      label.text = list.title 
      return label 
     } 

     view.addSubview(label) 
     print("Label Text: \(list.title)") 
    } 
} 

let url = URL(string: "https://jsonplaceholder.typicode.com/todos/") 

func callAPI(_ list: List) { 
    URLSession.shared.dataTask(with: url!, completionHandler: { 
    (data, response, error) in 
    if error != nil { 
     print(error!) 
     return 
    } 
    do { 
     let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSMutableArray 
     let array = json[0] as! [String:Any] 
     let title = array["title"] as! String 
     print("Title: \(title)") 

     list.title = title 
    } 
    catch let jsonError { 
     print(jsonError) 
    } 
    }).resume() 
} 
0

爲什麼在異步網絡功能中不使用closure

你的代碼發生了什麼事情是你派遣你的網絡調用(這需要花費大量的時間)。在網絡調用正在處理時,您的代碼將繼續執行。意味着您的線路label.text = title在網絡通話完成之前被調用。在某個時候,網絡通話完成並執行您的代碼以創建列表。但是,自設置標籤文本以來(以計算機方式)很長。

使用閉包,您可以指定希望代碼在JSON被提取,序列化並轉換爲List對象之後運行。

下面的代碼爲您的callAPI函數添加了閉包參數。像其他參數一樣,此參數的名稱爲completion。執行網絡調用後,您可以調用該參數,並在該點執行任何傳入的代碼。

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     callAPI { (list) in 
      let width = self.view.bounds.width 
      let height = self.view.bounds.height 
      let label = UILabel(frame: CGRect(x: 0, y: height/2 - 50, width: width, height: 50)) 
      label.backgroundColor = UIColor.red 
      label.text = list.title 
      DispatchQueue.main.async(execute: { 
       self.view.addSubview(label) 
      }) 
      print("Label Text: \(list.title)") 
     } 
    } 

    let url = URL(string: "https://jsonplaceholder.typicode.com/todos/") 

    func callAPI(completion: @escaping (_ list: List) -> Void) { 
     URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in 
      if error != nil { 
       print(error!) 
       return 
      } 
      do { 
       let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSMutableArray 
       let array = json[0] as! [String:Any] 
       let title = array["title"] as! String 
       print("Title: \(title)") 
       let list = List() 
       list.title = title 

       completion(list) 
      } 
      catch let jsonError { 
       print(jsonError) 
      } 
     }).resume() 
    } 
} 
0

試試這個代碼。

import UIKit 

class List { 
    var title = String() 
} 

class ViewController: UIViewController { 
    var list = List() 

let url = URL(string: "https://jsonplaceholder.typicode.com/todos/") 
override func viewDidLoad() { 
    super.viewDidLoad() 
    callAPI() 

} 

func setLable() { 
    let width = view.bounds.width 
    let height = view.bounds.height 
    let label: UILabel = { 
     let label = UILabel(frame: CGRect(x: 0, y: height/2 - 50, width: width, height: 50)) 
     label.backgroundColor = UIColor.red 
     label.text = list.title 
     return label 
    }() 
    self.view.addSubview(label) 
    print("Label Text: \(list.title)") 
} 


func callAPI() { 
    URLSession.shared.dataTask(with: url!, completionHandler: { 
     (data, response, error) in 
     if error != nil { 
      print(error!) 
      return 
     } 
     do { 
      let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSMutableArray 
      let array = json[0] as! [String:Any] 
      let title = array["title"] as! String 
      print("Title: \(title)") 
      self.list.title = title 
      self.setLable() 
     } 
     catch let jsonError { 
      print(jsonError) 
     } 
    }).resume() 
    } 
}