无法使用JSON数据更新UILabel

时间:2017-03-10 17:12:21

标签: ios json swift

我尝试使用JSON从REST API显示带有字符串的UILabel,但没有运气。我可以很好地将字符串打印到控制台,但是当尝试使用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()
}

4 个答案:

答案 0 :(得分:0)

您似乎想要替换这些行:

let list = List()
list.title = title

使用:

label.text = title

您创建,更新和弃放List个实例的代码,但不会尝试更新您的实际UILabel

创建和设置标签后,您还需要将呼叫移至callAPI()

答案 1 :(得分:0)

在ViewController中,您已创建了List()的实例,但callAPI()创建了自己的List()实例并更新了该title属性,而不是实例中的title属性。你的ViewController。

您可以删除callAPI()方法,将代码直接放入ViewController并直接更新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()
}

,或者您可以callAPIList()的实例作为参数并更新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()
}

答案 2 :(得分: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()
    }
}

答案 3 :(得分: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()
  }
}