How to display JSON into UILabel using UIPickerVie

2019-09-15 11:17发布

问题:

I have these JSON output using PHP.

[
    {"number":"001","name":"MIKE"},
    {"number":"002","name":"JOSH"}
]

In Swift, I managed to select "name" value and display it into UIPickerView like below.

DropdownJSON.swift

import UIKit

class DropdownJSON: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
    @IBOutlet var dropdownTxt: UITextField!
    @IBOutlet var dropdownPV: UIPickerView!

    @IBOutlet var numberLbl: UILabel!
    @IBOutlet var nameLbl: UILabel!

    var persons = [Person]()

    struct Person {
        var number:String
        var name: String

        init?(dict: [String:Any]) {
            guard let number = dict["number"] as? String, let name = dict["name"] as? String else {
                return nil
            }
            self.number = number
            self.name   = name
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        getDropdownJSON()
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return self.persons.count
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return persons[row].name
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        self.numberLbl.text      = self.persons[row].number
        self.nameLbl.text        = self.persons[row].name
        self.dropdownPV.isHidden = true
        self.dropdownTxt.resignFirstResponder()
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        if textField == self.dropdownTxt{
            self.dropdownPV.isHidden = false
        }
    }

    func getDropdownJSON() {
        let url = URL(string: "http://localhost/DropdownJSON.json")
        let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
            guard let data = data, error != nil else {
                print(error?.localizedDescription)
                return
            }
            if let array = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [[String:Any]] {
                self.persons = array.flatMap(Person.init)
                DispatchQueue.main.async {
                    self.dropdownPV.reloadAllComponents()
                }
            }
        }
        task.resume()
    }
}

But my goal is to display JSON output "number" into numberLbl and "name" into nameLbl in function pickerView (didSelectRow).

The reason is I want to post the numberLbl only later on. nameLbl is just to display on the screen page.

Is it possible ? Appreciate if someone can help on this matters.

UPDATE

Thanks.

回答1:

First of all you need to use URLSession.dataTask to get response from URL instead of NSData(contentsOf:). Also in Swift 3 use native URL and Data instead of NSURL and NSData.

Now the problem is you are not storing the number value form dictionary. The simplest way to manage this situation is to create struct and store both number and name value with it. After that create Array of that struct instead of Array of AnyObject.

struct Person {
    var number:String 
    var name: String 

    init?(dict: [String:Any]) {
        guard let number = dict["number"] as? String, let name = dict["name"] as? String else {
            return nil
        }
        self.number = number
        self.name = name
    }
}

Now declare one array of struct Person and with your getDropdownJSON method add data with in it.

var persons = [Person]()

func getDropdownJSON() {
    let url = URL(string: "http://localhost/getDropdownJSON.json")
    let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
        guard let data = data, error == nil else {
            print(error?.localizedDescription)
            return
        }
        if let array = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [[String:Any]] {
            self.persons = array.flatMap(Person.init)
            DispatchQueue.main.async {
                dropdownPV.reloadAllComponents()
            }
        }
    }
    task.resume()
}

Now in PickerViewDelegate method use this array to fill its component.

func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return self.persons.count
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return persons[row].name
}

Now in didSelectRow you need to simply access array object and you will be get the number and name both.

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    if row >= self.persons.count { 
        return
    }

    self.numberLbl.text = self.persons[row].number
    self.nameLbl.text = self.persons[row].name
    self.dropdownPV.isHidden = true
    self.dropdownTxt.resignFirstResponder()
}