使用 Alamofire 使用 JSON 数组填充 UIPickerView 时遇到问题 |迅速
Posted
技术标签:
【中文标题】使用 Alamofire 使用 JSON 数组填充 UIPickerView 时遇到问题 |迅速【英文标题】:Trouble populating UIPickerView with JSON array using Alamofire | Swift 【发布时间】:2019-07-02 18:28:54 【问题描述】:基本上我有一个 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 响应替换硬编码数组?
【问题讨论】:
请不要在 Swift 中使用NSURL
、NSData
、NSArray
、NSDictionary
、.mutableContainers
和 AnyObject
(用于 JSON 数据)。使用本机类型。 Swift 变量名以小写字母开头。并且从不使用同步 Data(contentsOf
从远程 URL 加载数据。不要那样做。
我很欣赏这些指针,为什么“使用同步 Data(contentsOf”从远程 URL 加载数据是不好的
它阻塞了线程。这会导致糟糕的用户体验。想象一下服务器目前不可用......
【参考方案1】:
你使用了很多不好的做法
不要在 Swift 中使用NSURL
、NSData
、NSArray
、NSDictionary
和 AnyObject
(用于 JSON 数据)。使用原生类型。
不要在 Swift 中使用 .mutableContainers
。该选项毫无意义。省略options
参数
Swift 变量名以小写字母开头。
永远不会使用同步 Data(contentsOf
从远程 URL 加载数据。使用异步URLSession
最有效的解决方案是使用Decodable
解码JSON
在类之外声明结构
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$0.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$0["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 请求来说太过分了
【讨论】:
哦,当然,我没有想到这一点。你熟悉如何在 UIPickerView 中实现 JSON 响应吗? 声明model
为var
iable,将结果赋值给model
:self.model = result.map$0.model
并在DispatchQueue闭包中重新加载picker数据:self.pickerview.reloadAllComponents()
您能否在回答中详细说明这一点?我以前做过类似的事情,但没有奏效。
如果在 Alamofire 中也是 JSON Post 请求,我可以做什么:let parameters: Parameters = ["customer": "\(Customer)"] Alamofire.request(url, method: .post, parameters: parameters).responseString response in print(response)
例如,没有它我可以完成吗?
您的问题没有提到 POST 请求。你也可以用URLSession
来做。顺便说一句,Alamofire
很大程度上基于URLSession
以上是关于使用 Alamofire 使用 JSON 数组填充 UIPickerView 时遇到问题 |迅速的主要内容,如果未能解决你的问题,请参考以下文章
如何使用来自 Alamofire 的 JSON 数据填充 tableview?
使用 AlamoFire 获取数据以根据 UISearchBar 值填充 UITableView