I have a really strange error, the application in this application uses the pattern-view-controller, in the view I use a UIPickerView to display names. Values should be shown in RisorseUmaneUIPicker! The strange thing is that everything works while when you text the application on mobile devices in 3g sometimes, the UIPickerView remains empty. How can I solve this?
I checked the json request with postman and it is always correct
View:
class RisorseUmaneViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITableViewDelegate, UITableViewDataSource {
//Dichiarazione Oggetti
//L'array User contiene le informazione su tutti gli utenti presenti nel database
private var UserLoad: [UserStruct] = []
private var RisorseUmaneUIPicker: UIPickerView = UIPickerView()
private let datePicker: UIDatePicker = UIDatePicker()
private let StartPicker: UIDatePicker = UIDatePicker()
private let EndPicker: UIDatePicker = UIDatePicker()
private let PausaPicker: UIDatePicker = UIDatePicker()
private var textView: UITextView = UITextView()
private var RisoseUmaneTableView: UITableView!
private var RisorseUmaneLoad: [RisorsaUmanaStruct] = []
private var SwitchRapportino: UISwitch = UISwitch()
//L'oggetto RisorsaUmana Rappresenta la risorsa che verrà inserita
public var Cantiere: Cantiere
private var RisorsaSelezionata: RisorsaUmana?
private var Extensioni: Extend = Extend()
public var Stato: String = "Inserimento"
private var RisorsaRapportino: Bool = false;
init(CantiereInterno: Cantiere) {
self.Cantiere = CantiereInterno
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
hideKeyboardWhenTappedAround()
self.view.backgroundColor = UIColor.white
self.navigationController?.setNavigationBarHidden(false, animated: true)
self.navigationItem.title = "Risorse Umane"
InitRisorseUmaneViewController();
//Modifica UiPickerView delle Risorse con l'utente che ha effettuato il login
print("Login di : \(UserLoginDefault.Username)")
selectPicker(withText: UserLoginDefault.Username)
}
//Funzione di Configurazione Iniziale della View
private func InitRisorseUmaneViewController() {
//inizializzo il Cantiere
let displayWidth: CGFloat = self.view.frame.width
//Carico le Risorse
CaricaRisorse()
//Configurazione Label Risorsa
let label = UILabel(frame: CGRect(x: (self.view.frame.width / 2) - 150, y: 65, width: 90, height: 24))
label.font = UIFont(name: "HelveticaNeue-Bold", size: 16.0)
label.textAlignment = .center
label.text = "Risorsa: "
self.view.addSubview(label)
//Configurazione :impostazioni picker view
self.RisorseUmaneUIPicker = UIPickerView(frame: CGRect(x: (self.view.frame.width / 2) - 70, y: 50, width: 200, height: 50))
self.RisorseUmaneUIPicker.delegate = self
self.RisorseUmaneUIPicker.dataSource = self
self.RisorseUmaneUIPicker.backgroundColor = UIColor.white
self.view.addSubview(RisorseUmaneUIPicker)
//Configuro il DataTime Picker per la data
self.datePicker.frame = CGRect(x: 10, y: 100, width: self.view.frame.width, height: 80)
self.datePicker.timeZone = NSTimeZone.local
self.datePicker.backgroundColor = UIColor.white
self.datePicker.datePickerMode = UIDatePickerMode.date;
//Aggiunto un evento quando viene modificato il valore del datePicker
self.datePicker.addTarget(self, action: #selector(RisorseUmaneViewController.datePickerValueChanged(_:)), for: .valueChanged)
self.view.addSubview(datePicker)
//Congiurazione Ore di Inizio e Fine
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
let dateStart = dateFormatter.date(from: "08:00")
let dateEnd = dateFormatter.date(from: "17:30")
let datePausa = dateFormatter.date(from: "01:30")
//Configuro il DataPicker di Start
self.StartPicker.frame = CGRect(x: (self.view.frame.width / 2) - 90, y: 190, width: 100, height: 40)
self.StartPicker.timeZone = NSTimeZone.local
self.StartPicker.backgroundColor = UIColor.white
self.StartPicker.datePickerMode = UIDatePickerMode.time
self.StartPicker.date = dateStart!
self.StartPicker.addTarget(self, action: #selector(RisorseUmaneViewController.SetDataInizio(sender:)), for: .valueChanged)
self.StartPicker.minuteInterval = 30
self.view.addSubview(StartPicker)
//Configuro il DataPicker di End
self.EndPicker.frame = CGRect(x: (self.view.frame.width / 2) + 60, y: 190, width: 100, height: 40)
self.EndPicker.timeZone = NSTimeZone.local
self.EndPicker.backgroundColor = UIColor.white
self.EndPicker.datePickerMode = UIDatePickerMode.time
self.EndPicker.date = dateEnd!
self.EndPicker.addTarget(self, action: #selector(RisorseUmaneViewController.SetDataFine(sender:)), for: .valueChanged)
self.EndPicker.minuteInterval = 30
self.view.addSubview(EndPicker)
//Configuro il DataPicker di Pausa
self.PausaPicker.frame = CGRect(x: (self.view.frame.width / 2) - 30, y: 250, width: 100, height: 40)
self.PausaPicker.timeZone = NSTimeZone.local
self.PausaPicker.backgroundColor = UIColor.white
self.PausaPicker.datePickerMode = UIDatePickerMode.time
self.PausaPicker.date = datePausa!
self.PausaPicker.addTarget(self, action: #selector(RisorseUmaneViewController.SetPausa(sender:)), for: .valueChanged)
self.PausaPicker.minuteInterval = 30
self.view.addSubview(PausaPicker)
//Configurazione Testo TextView
self.textView = UITextView(frame: CGRect(x: 0, y: 300, width: displayWidth, height: 85))
self.automaticallyAdjustsScrollViewInsets = false
textView.font = UIFont(name: "HelveticaNeue-Bold", size: 18.0)
textView.textAlignment = NSTextAlignment.justified
textView.textColor = UIColor.blue
textView.backgroundColor = UIColor.lightGray
self.view.addSubview(textView)
//Bottone per inserimento:
let ImageInserisci = UIImage(named: "inserisci.png") as UIImage?
let ButtonInserisciRisorsaUmana = UIButton()
ButtonInserisciRisorsaUmana.frame = CGRect(x: (self.view.frame.width / 2) - 180, y: 395, width: 80, height: 80)
ButtonInserisciRisorsaUmana.setImage(ImageInserisci, for: .normal)
ButtonInserisciRisorsaUmana.setTitleColor(UIColor.black, for: .normal)
ButtonInserisciRisorsaUmana.set(image: ImageInserisci, attributedTitle: NSAttributedString(string: "Inserisci"), at: UIButton.Position(rawValue: 1)!, width: 30, state: UIControlState.normal)
ButtonInserisciRisorsaUmana.addTarget(self, action: #selector(InserisciRisorsaButtonAction), for: .touchUpInside)
self.view.addSubview(ButtonInserisciRisorsaUmana)
//Bottone per tornare a schermata principale
let ImageReturn = UIImage(named: "return.png") as UIImage?
let buttonReturn = UIButton()
buttonReturn.frame = CGRect(x: (self.view.frame.width / 2) - 30, y: 395, width: 80, height: 80)
buttonReturn.backgroundColor = UIColor.white
buttonReturn.setImage(ImageReturn, for: .normal)
buttonReturn.setTitle("Go Home", for: .normal)
buttonReturn.addTarget(self, action: #selector(Return), for: .touchUpInside)
self.view.addSubview(buttonReturn)
//Configuro lo UISwitch per l'inserimento delle risorse nel cantiere
let labelRapportino = UILabel(frame: CGRect(x: (self.view.frame.width / 2) + 80, y: 395, width: 130, height: 21))
labelRapportino.text = "Rapportino?"
labelRapportino.font = UIFont(name: "HelveticaNeue-Bold", size: 16.0)
self.view.addSubview(labelRapportino)
SwitchRapportino = UISwitch(frame: CGRect(x: (self.view.frame.width / 2) + 100, y: 430, width: 0, height: 0))
SwitchRapportino.setOn(false, animated: true)
SwitchRapportino.addTarget(self, action: #selector(RisorseUmaneViewController.switchValueDidChange(sender:)), for: .valueChanged)
self.view.addSubview(SwitchRapportino)
//Stato Inserimento: l'utente sta inserendo delle risorse dentro una cantier
if(Stato == "Inserimento") {
RisorsaSelezionata = RisorsaUmana(CantiereInterno: Cantiere)
//Configurazione table view
RisoseUmaneTableView = UITableView(frame: CGRect(x: 0, y: 500, width: displayWidth, height: self.view.frame.height - 500))
RisoseUmaneTableView.register(CustomTableViewCellArticolo.self, forCellReuseIdentifier: "MyCell")
RisoseUmaneTableView.dataSource = self
RisoseUmaneTableView.delegate = self
RisoseUmaneTableView.tableFooterView = UIView()
RisoseUmaneTableView.rowHeight = 60
RisoseUmaneTableView.layer.borderWidth = 2.0
self.view.addSubview(RisoseUmaneTableView)
//Carica Le risorse Umane e chiamo i Metodi di configurazione
CaricaRisorseCantiere()
}
SetPausa(sender: PausaPicker)
SetDataInizio(sender: StartPicker)
SetDataFine(sender: EndPicker)
datePickerValueChanged(datePicker)
SwitchRapportino.isHidden = false
labelRapportino.isHidden = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func selectPicker(withText text: String) {
print("Testo: \(text)")
if let index = self.UserLoad.index(where: { $0.Username == text }) {
print("Indice di riga: \(index)")
RisorseUmaneUIPicker.selectRow(index, inComponent: 0, animated: true)
self.RisorseUmaneUIPicker.reloadAllComponents()
}
else {
print("text not found")
}
}
//Funzione per il caricamento delle risorse Umane
func CaricaRisorse() {
DispatchQueue.global(qos: .userInteractive).async {
let rtemp = User()
rtemp.CaricaUtenti(completion: { result in
self.UserLoad = result
self.RisorseUmaneUIPicker.reloadAllComponents()
});
}
}
@objc func SetPausa(sender: UIDatePicker) {
RisorsaSelezionata?.SetOrePausa(Pausa: Extensioni.CastFromDateToString_SqlServer_Pausa(mydate: PausaPicker.date))
}
@objc func SetDataFine(sender: UIDatePicker) {
RisorsaSelezionata?.SetOreFine(OreFine: Extensioni.CastFromDateToString_SqlServer_DateTime(mydate: EndPicker.date))
}
@objc func SetDataInizio(sender: UIDatePicker) {
RisorsaSelezionata?.SetOreInizio(OreInizio: Extensioni.CastFromDateToString_SqlServer_DateTime(mydate: StartPicker.date))
}
@objc func InserisciRisorsaButtonAction(sender: UIButton!) {
print("\n Id Risorsa: \(String(describing: RisorsaSelezionata?.GetIdUtente()))")
if(textView.text.isEmpty || RisorsaSelezionata?.GetIdUtente() == 0) {
let alertController = UIAlertController(title: title, message: "Attenzione non hai compilato tutti i campi", preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
self.present(alertController, animated: true, completion: nil)
}
else {
RisorsaSelezionata?.SetDescrizione(Descrizione: textView.text)
RisorsaSelezionata?.SetRisorsaRapporto(RisorsaRapportino: RisorsaRapportino)
if(Stato == "Inserimento") {
RisorsaSelezionata?.InserisciRisorsa(completion: { result in
if(result == true) {
self.CaricaRisorseCantiere()
}
else {
let alertController = UIAlertController(title: "Errore", message: "Non sono riuscito ad inserire la risorsa!", preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
self.present(alertController, animated: true, completion: nil)
}
})
}
}
}
@objc func Return(sender: UIButton!) {
//self.performSegueToReturnBack()
let CantiereSelezionato = GestioneCantieriViewController(CantiereSet: self.Cantiere)
self.present(CantiereSelezionato, animated: true, completion: nil)
}
//Metodo delegato che ritorna il numero di righe
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return UserLoad.count
}
// Metodo delegato che ritorna il valore mostrato nella riga
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
RisorsaSelezionata?.SetIdUtente(IdUtente: UserLoad[row].IdUtente)
return UserLoad[row].Username
}
// Metodo Delato Chiamao quando viene selezionata unarigha
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
print("\n UserLoad[row].IdUtente \(UserLoad[row].IdUtente!)")
RisorsaSelezionata?.SetIdUtente(IdUtente: UserLoad[row].IdUtente!)
print("\n ID Risorsa \(String(describing: RisorsaSelezionata?.GetIdUtente()))")
}
//Number of Columns into UIPickerView
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
//this func get select Date from UIDatePicker
@objc func datePickerValueChanged(_ sender: UIDatePicker) {
RisorsaSelezionata?.SetData(Data: Extensioni.CastFromDateToString_SqlServer_DateTime(mydate: sender.date))
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return RisorseUmaneLoad.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
RisoseUmaneTableView.beginUpdates()
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! CustomTableViewCellArticolo
cell.layer.cornerRadius = 10
cell.layer.borderWidth = 1.0
cell.layer.borderColor = UIColor.gray.cgColor
cell.layer.masksToBounds = true
cell.labCodArt.text = RisorseUmaneLoad[indexPath.row].Risorsa
cell.labDescrizione.text = RisorseUmaneLoad[indexPath.row].Descrizione
cell.labPrezzo.text = ""
RisoseUmaneTableView.endUpdates()
return cell
}
func CaricaRisorseCantiere() {
if(Stato == "Inserimento") {
let rtemp = RisorsaUmana(CantiereInterno: Cantiere)
rtemp.CaricaRisorseUmaneCantiere(completion: { result in
self.RisorseUmaneLoad.removeAll()
self.RisorseUmaneLoad = result
DispatchQueue.main.async {
self.RisoseUmaneTableView.reloadData()
}
});
}
}
......
Controller:
func CaricaUtenti(completion: @escaping ([UserStruct]) -> Void) {
DispatchQueue.global(qos: .userInteractive).async {
let rtemp = UserModel()
rtemp.CaricaRisorse(completion: { result in
completion(result)
})
}
}
Model:
func CaricaRisorse(completion: @escaping ([UserStruct]) -> ()) {
DispatchQueue.global(qos: .userInteractive).async {
let jsonrequest = JSON()
let jsonarray: [String: Any] = ["Default": "0"]
jsonrequest.GetArray(Tipo: "User", Router: "/RisorseUmane/CaricaRisorse", ValueArray: jsonarray, completion: { result in
completion(result as! [UserStruct])
})
}
}
func GetArray(Tipo: String, Router: String, ValueArray: [String: Any], completion: @escaping (_ ret: Codable) -> ()) {
let semaphore = DispatchSemaphore(value: 1)
semaphore.wait()
let db = Database()
let json: [String: Any] = ValueArray
let jsonData = try? JSONSerialization.data(withJSONObject: json)
var request = URLRequest(url: URL(string: db.GetServerURL() + Router)!)
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")
request.httpMethod = "POST"
request.httpBody = jsonData
URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
print(error!.localizedDescription)
}
guard let data = data else { return }
do {
if(Tipo == "User") {
let value = try JSONDecoder().decode([UserStruct].self, from: data)
completion(value)
}
} catch let error {
print("Error JSON: ", error)
}
}.resume()
semaphore.signal()
}
You can install "Network Link Conditioner" from Xcode menu:
Open Developers Tools>More Developers Tools. This tool allows you to test under different network conditions.Handler passed to
URLSesssion.dataTaskshould probably pass information about success or failure back to caller. It now simply returns if there has been an error if data isnil. Consider adding extra value besides data to handler. For example,_ success: Boolcould be passedfalsein case of error if data is missing.