Thiha Aung
Thiha Aung

Reputation: 5096

Load data from json using UIPickerView

My Current View Controller is like this

import UIKit
import Alamofire

class ViewController: UIViewController , UIPickerViewDelegate, UIPickerViewDataSource{

@IBOutlet var venuePicker : UIPickerView?

var result = [String:String]()

var resultArray = [String]()

override func viewDidLoad() {

    self.venuePicker?.delegate = self

    Alamofire.request(.POST, "http://example.com/xxx/xx/xx").responseJSON() {
        (request, response, jsonData, error) in

        var venues = JSON(jsonData!)

        let d = venues.dictionaryValue

        for (k, v) in venues {
            self.result[k] = v.arrayValue[0].stringValue
        }
        self.resultArray = self.result.values.array
        self.venuePicker?.reloadAllComponents()
    }

}

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

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

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
    return resultArray[row]
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

I don't know how to show value to UIPickerView from my json dictionary.i don't want key to show at UIPickerView.I am now stuck at "?????" statement.

This is my output for result

[C2517: ORIX Kobe Nyusatsu, C2510: NPS Sendai Nyusatsu, C2033: JU Gunma, C2053: KAA Kyoto, C2035: JU Ibaraki, C2077: USS Gunma, C2024: ISUZU Kobe, C2505: NAA Osaka Nyusatsu, C2529: SMAP Sapporo Nyusatsu, C2502: L-Up PKobeNyusatsu, C2005: ARAI Sendai, C2072: TAA Minami Kyushu]

Please help!!!

Upvotes: 3

Views: 5182

Answers (2)

ljk321
ljk321

Reputation: 16770

Alamofire is totally async. It means that the block code will be executed when the data is ready. By then, the PickerView is already loaded, with an empty Array. That's the reason why the PickerView is empty. So in order to display the data we want, we need to force the PickerView to reload:

override func viewDidLoad() {
    self.venuePicker?.delegate = self // This should be outside the block, my bad.
    //...
    Alamofire.request(...) {in
        //...
        venuePicker?.reloadAllComponents() // hopefully this will work
    } 

If you're not familliar with the concept of async programming, you can also choose to use sync way. Using this code I wrote https://github.com/skyline75489/swift-playground/blob/master/swift-playground%2FRequests.swift, we can easily send sync requests.

if let jsonData = Requests.get("YOUR_URL") {
     let venues = JSON(jsonData)
     //...
}

The reason why we have async is sometimes the data can be big and using sync way will cause the viewDidLoad to take forever to load. That's awful for user experience. However, if the data is small. Sync way can finish the task fast enough that users won't feel it. It's totally OK to use sync ways.

Upvotes: 0

rakeshbs
rakeshbs

Reputation: 24572

If you wanted to show data to a picker view, use declare 2 arrays as properties instead.

var resultKeys = [String]()
var resultValues = [String]()

Inside your viewDidLoad function

var venues = JSON(jsonData!)

let d = venues.dictionaryValue

for (k, v) in venues {
    resultKeys.append(k)
    resultValues.append(v)
}

venuePicker.dataSource = self
venuePicker.reloadAllComponents()

Then inside titleForRow

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
    return resultValues[row]
}

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

This way resultKeys[pickerView.selectedRowInComponent(0)] will return the key for the selected value.

Upvotes: 1

Related Questions