使用 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 响应替换硬编码数组?
您使用了很多不良做法
- 不要在 [= 中使用
NSURL
、NSData
、NSArray
、NSDictionary
和 AnyObject
(对于 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 请求来说太过分了
基本上我有一个 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 响应替换硬编码数组?
您使用了很多不良做法
- 不要在 [= 中使用
NSURL
、NSData
、NSArray
、NSDictionary
和AnyObject
(对于 JSON 数据) 60=]。使用本机类型。 - 不要在 Swift 中使用
.mutableContainers
。该选项毫无意义。省略options
参数 - Swift 变量名以小写字母开头。
- 永远不会 使用同步
Data(contentsOf
从远程 URL 加载数据。使用异步URLSession
最有效的解决方案是用 Decodable
在 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 请求来说太过分了