My goal is to draw controls dynamically from an array of metadata that comes from the backend for example this
"MetadataServicio": [
{
"DATA_TYPE": "Varchar",
"ERROR_DESC": "",
"FIELD_LENGTH": "25",
"FIELD_TYPE": "Textbox",
"FK_ID_SERVICIO": "009",
"IS_QUERY": "0",
"LABEL": "Dato",
"ORDEN": "2",
"VALIDATION": "null",
"VALUE": ""
},
{
"DATA_TYPE": "",
"ERROR_DESC": "",
"FIELD_LENGTH": "",
"FIELD_TYPE": "Combo",
"FK_ID_SERVICIO": "009",
"IS_QUERY": "0",
"LABEL": "Identificador",
"ORDEN": "1",
"VALIDATION": "",
"VALUE": "[{\"Valor\":\"C\u00e9dula\"},{\"Valor\":\"Cuenta\"}]"
}
]
This here means that I have a combo that will have 2 values ID and Account, but there could be n combos that I had to create dynamically
For this create a class containing
class ArrayComboBoxDatas {
var selectedObject : String
var pickerObject : UIPickerView
var destinationEntities : [String]
var orden : String
var textField:TextField
}
And in my class where I add the controls I have an array of said class
var arrayCombosBoxsOn = [ArrayComboBoxDatas]()
Then to add the combo I do:
func agregarComboBox(metaDato:ServiceMetaData){
var txtAux = TextField.init(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
txtAux.backgroundColor = UIColor.white
txtAux.textColor = UIColor.black
txtAux.tag = Int(metaDato.ORDEN)!
var comboBoxOnAux = ArrayComboBoxDatas.init()
comboBoxOnAux.selectedObject = ""
let pickewViewAux = UIPickerView()
pickewViewAux.tag = Int(metaDato.ORDEN)!
comboBoxOnAux.pickerObject = pickewViewAux
comboBoxOnAux.orden = metaDato.ORDEN
var arrayStringStringAux = [String]()
let keysValues = metaDato.VALUE
let data = keysValues.data(using: .utf8)!
do {
if let jsonArray = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [Dictionary<String,Any>]
{
for valores in jsonArray {
var valor = valores["Valor"] as! String
arrayStringStringAux.append(valor)
}
} else {
print("bad json")
}
} catch let error as NSError {
print(error)
}
comboBoxOnAux.destinationEntities = arrayStringStringAux
self.arrayCombosBoxsOn.append(comboBoxOnAux)
}
What this does is fill my Array of combos which contains reference to the box created to the picker of it and its data, to then go through this entire array and create the connections of the pickers
func createPickers(){
for info in arrayCombosBoxsOn{
let toolbar = UIToolbar()
toolbar.sizeToFit()
let done = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(donePressedGeneric))
toolbar.setItems([done], animated: false)
info.textField.inputAccessoryView = toolbar
info.textField.inputView = info.pickerObject
info.pickerObject.delegate = self
info.pickerObject.dataSource = self
info.pickerObject.tag = 4
self.viewStack.addArrangedSubview(info.textField)
}
}
The theme comes from the delegate
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
switch pickerView.tag {
case 0:
return CommonViewController.OrigenesCuentas.count
case 1:
return servicesTypesArray.count
case 2:
return servicesArray.count
default:
}
How could I, based on what I have, dynamically place the amount and other data? How could I resolve showing combos dynamically easier than a uipickersview? , I am open to achieving it in the way I thought or looking for more efficient alternatives, thanks
Your approach is very interesting, I would solve it this way: In addition to having an array of combos self.arrayCombosBoxsOn I would have another array or dictionary of values, it would be something like this:
This is filled by your addComboBox function with the tag that you are assigning to the picker as the key of the dictionary and the array of values as the value
So the delegate would be something like this:
The delegate of the titles or cells would be a bit more complicated because you would have to order the dictionary of values so that it remains as an array.
I hope it works.