使用 Alamofire 使用 JSON 数组填充 UIPickerView 时遇到问题 | Swift

Trouble populating UIPickerView with JSON array using Alamofire | Swift

基本上我有一个 textField,按下时需要打开一个 UIPickerView,其中的选择来自 JSON

我在选择 UItextField 和从 Swift 中的 JSON 创建数组时分别触发了 UIPickerView,但在组合起来时遇到了一些麻烦。

对于 JSON 我使用 Almofire 只是因为它简化了过程 并且 UIPickerView 是以编程方式编写的。

我正在使用的 JSON 看起来像这样:

[{“model”:”model1”},{“model":"model2”},
{“model":"model3”},{“model":"model4”},{“model":"model5”},{“model":"model6”}]

Almofire 目前看起来是这样的:

        let url = NSURL(string: "https://www.test.com/test/test")

        let data = NSData(contentsOf: url! as URL)
        var tmpValues = try! JSONSerialization.jsonObject(with: data! as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSArray
        tmpValues = tmpValues as NSArray
        reloadInputViews()


        for candidate in tmpValues {
            if let cdict = candidate as? NSDictionary {

                //model is the column name in sql/json
                let model = cdict["model"]
                self.values.append(model! as AnyObject)


            }
        }

触发 textField 打开 UIPickerView 是使用以下代码完成的:

import UIKit

class ViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {


    @IBOutlet weak var TextField: UITextField!

    let model = ["model1","model2"]

    var pickerview = UIPickerView()

    override func viewDidLoad() {
        super.viewDidLoad()


        TextField.inputView = pickerview
        TextField.textAlignment = .center
        TextField.placeholder = "Select Your Model"

        pickerview.delegate = self
        pickerview.dataSource = self

        // Do any additional setup after loading the view, typically from a nib.
    }

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

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

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

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        TextField.text = Names[row]
    }

}

如何用 JSON 响应替换硬编码数组?

您使用了很多不良做法

  • 不要在 [= 中使用 NSURLNSDataNSArrayNSDictionaryAnyObject(对于 JSON 数据) 60=]。使用本机类型。
  • 不要在 Swift 中使用 .mutableContainers。该选项毫无意义。省略 options 参数
  • Swift 变量名以小写字母开头。
  • 永远不会 使用同步 Data(contentsOf 从远程 URL 加载数据。使用异步 URLSession

最有效的解决方案是用 Decodable

解码 JSON

在 class 之外声明结构

struct Model : Decodable {
    let model : String
}

将选择器源声明为变量和复数形式

var models = [String]()

viewDidLoad末尾插入

let url = URL(string: "https://www.test.com/test/test")!
let dataTask = URLSession.shared.dataTask(with: url) { data, _, error in
    if let error = error { print(error); return }
    do { 
        let result = try JSONDecoder().decode([Model].self, from: data!)
        self.models = result.map{[=12=].model}
        DispatchQueue.main.async {
          self.pickerview.reloadAllComponents()
        }
    } catch { print(error) }
}
dataTask.resume()

即使使用 JSONSerialization(没有 Model 结构)也非常简单

let url = URL(string: "https://www.test.com/test/test")!
let dataTask = URLSession.shared.dataTask(with: url) { data, _, error in
    if let error = error { print(error); return }
    do { 
        if let result = try JSONSerialization.jsonObject(with: data!) as? [[String:String]]
            self.models = result.compactMap{[=13=]["model"]}
            DispatchQueue.main.async {
              self.pickerview.reloadAllComponents()
            }
        }
    } catch { print(error) }
}
dataTask.resume()

选择器数据源方法是

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

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

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    TextField.text = models[row]
}

Alamofire 对于一个简单的 GET 请求来说太过分了