使用 UIPickerView 从 json 加载数据

Posted

技术标签:

【中文标题】使用 UIPickerView 从 json 加载数据【英文标题】:Load data from json using UIPickerView 【发布时间】:2015-01-27 09:22:57 【问题描述】:

我的当前视图控制器是这样的

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.




我不知道如何从我的 json 字典中向 UIPickerView 显示值。我不想在 UIPickerView 上显示键。我现在卡在“?????”声明。

这是我的结果输出

[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]

请帮忙!!!

【问题讨论】:

【参考方案1】:

如果您想向选择器视图显示数据,请改用声明 2 个数组作为属性。

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

在您的 viewDidLoad 函数中

var venues = JSON(jsonData!)

let d = venues.dictionaryValue

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


venuePicker.dataSource = self
venuePicker.reloadAllComponents()

然后在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

这样resultKeys[pickerView.selectedRowInComponent(0)] 将返回所选值的键。

【讨论】:

我试过了。它在 resultValues.append(v) 中有错误。编译器说“JSON 不能转换为字符串”@rakeshbs。谢谢你的帮助【参考方案2】:

Alamofire 是完全异步的。这意味着当数据准备好时将执行块代码。到那时, PickerView 已经加载,带有一个空数组。这就是 PickerView 为空的原因。所以为了显示我们想要的数据,我们需要强制 PickerView 重新加载:

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

如果你不熟悉异步编程的概念,你也可以选择使用同步方式。使用我写的这段代码https://github.com/skyline75489/swift-playground/blob/master/swift-playground%2FRequests.swift,我们可以轻松发送同步请求。

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

我们使用异步的原因是有时数据可能很大,使用同步方式会导致viewDidLoad 永远加载。这对用户体验来说太糟糕了。但是,如果数据很小。同步方式可以快速完成任务,用户感觉不到。使用同步方式是完全可以的。

【讨论】:

我没有得到任何结果@skyline。我必须修复 self.venuePicker?.delegate 而不是你的。程序运行顺利。但是,选择器上似乎没有数据 我已经更新了代码。没有 UIPickerViewDataSource 和 Delegate。如果我添加这个我在 UIViewController 上遇到错误 类型“ViewController”不符合协议“UIPickerViewDataSource”。这是编译时错误 @Thiha6245 DataSource 可以去掉,但是delegate 是必须的。没有委托,选择器视图上不会显示任何内容。 我通过重写3个Delegate和Datasource的函数来修复它。但是,UIPickerView仍然显示为空。

以上是关于使用 UIPickerView 从 json 加载数据的主要内容,如果未能解决你的问题,请参考以下文章

使用远程 JSON 数组填充 UIPIckerView

UIPickerView 不会显示从 NSUserDefaults 加载的数据 - 加载数据时应用程序崩溃

UIPickerView 不会显示从 NSUserDefaults 加载的数据

后退按钮刷新/重新加载 uipickerview 内容

带有图像和文本的 UIPickerView 快速?

从另一个 ViewController 重新加载 UIPickerView 的数据