1

I have a problem with my UITableView. I have 3 views with navigation controller. The second one have a table, the third is a search with some values. I want to click on button search (third view) and open second view and update the table. But not update. To work I have to return to first view and open again second view.

Second view code:

class Empresa: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate{

let textCellIdentifier = "cell"
var menu:[[String]] = [[]]
var buscaEmp:BuscadorEmpresa = BuscadorEmpresa()


@IBOutlet weak var tablaVista: UITableView!


override func viewDidLoad() {
    super.viewDidLoad()
    recuperaEmpresas()
    tablaVista.delegate = self
    tablaVista.dataSource = self

}

func recuperaEmpresas(){

    menu = buscaEmp.getEmpresas()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return menu.count
}




func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! CustomTableViewCell

    let row = indexPath.row
    cell.nombreEmp.text = menu[row][0]
    return cell

}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    recuperaEmpresas()
    self.tablaVista.reloadData()

}

As you can see I reload my tableView (tablaVista) on viewWillAppear but don't update.

RecuperaEmpresa() call this method:

 func getEmpresas() -> [[String]]{
    NSUserDefaults.standardUserDefaults().synchronize()

    var array = [[""]]
     if((NSUserDefaults.standardUserDefaults().arrayForKey("ARRAYEMPRESA")) != nil){
array = NSUserDefaults.standardUserDefaults().arrayForKey("ARRAYEMPRESA")! as! [[String]]
return array
}
return array }

I was debugging and it's like getEmpresa don't update first time

EDIT:

GetEmpresa not return the last value the first time, but if I print return correct value. The problem must be NSUSERDEFAULT

EDIT WITH IMAGES

Step 1

Step 2

Step 3

Step 4

Step 5

EDITED FOR Alessandro Ornano

Finally my tableView reload but I see an instant my last values and change it with news. I use that:

Second view:

let textCellIdentifier = "cell"
var menu:[[String]] = [[]]
//var buscaEmp:BuscadorEmpresa = BuscadorEmpresa()


@IBOutlet weak var tablaVista: UITableView!


override func viewDidLoad() {

    super.viewDidLoad()
    recuperaEmpresas()
    tablaVista.delegate = self
    tablaVista.dataSource = self

}

func recuperaEmpresas(){
    self.menu = NSUserDefaults.standardUserDefaults().arrayForKey("ARRAYEMPRESA")! as! [[String]]
    //self.menu = buscaEmp.getEmpresas()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return menu.count
}




func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! CustomTableViewCell

    let row = indexPath.row
    cell.nombreEmp.text = menu[row][0]
    return cell

}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    recuperaEmpresas()
    viewDidLoad()
    self.tablaVista.reloadData()

}

Third view button call this methods:

request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in
        if error != nil
        {
            print("error=\(error)")
            return
        }

        let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
        var err: NSError?
        do{
            let myJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)

            let jsonEmpresas = myJSON["TablaEmp"]!!["item"]
            let empresas: [[String: AnyObject]]

            if let multipleEmpresas = jsonEmpresas as? [[String: AnyObject]] {
                empresas = multipleEmpresas
            } else if let singleEmpresa = jsonEmpresas as? [String: AnyObject] {
                empresas = [singleEmpresa]
            } else {
                empresas = []
            }

            for empresa in empresas{
                let zcif = empresa["Zcif"] as? String
                let zcccp = empresa["Zcccp"] as? String
                let zfax = empresa["Zfax"] as? String
                let zdocu = empresa["Zdocu"] as? String
                self.arrayEmpresas.append([zcif!, zcccp!, zfax!, zdocu!])


            }
            NSUserDefaults.standardUserDefaults().setObject(self.arrayEmpresas, forKey:"ARRAYEMPRESA")
            NSUserDefaults.standardUserDefaults().synchronize()


        }catch { print(error)}
    }
    task.resume()

And

 func back(){
    navigationController?.popViewControllerAnimated(true)
}

getMethod:

func getEmpresas() -> [[String]]{
    NSUserDefaults.standardUserDefaults().synchronize()

    var array = [[""]]

    if((NSUserDefaults.standardUserDefaults().arrayForKey("ARRAYEMPRESA")) != nil){
    array = NSUserDefaults.standardUserDefaults().arrayForKey("ARRAYEMPRESA")! as! [[String]]
    return array
    }
    return array
}
Aris Guimerá
  • 1,095
  • 1
  • 12
  • 27
  • Are you stating that the data to be displayed in the `TableView` is modified from within the second `ViewController` itself and the change is not updated in the `TableView`? Where is the user defaults modified? – Mathews May 19 '16 at 08:58
  • Update `serachValue` in thirdView's `viewWillDisappear:` method and reload your table in secondView's `viewDidAppear:` method – TheTiger May 19 '16 at 09:51
  • @TheTiger I tried but still don't work – Aris Guimerá May 19 '16 at 11:19

2 Answers2

1

When you have this kind of issue many times there are involved synchronism between sampling data and UI update. In your code I dont know where you get this data, how long it takes to arrive and how you set this array on NSUserDefaults. So, if you can't see immediatly your UI updates probably you launch reloadData (main thread) too early because there are still operations to the background thread (http server queries, data fetching...)

You can also write a more elegant:

func getEmpresas() -> [String] {
    NSUserDefaults.standardUserDefaults().synchronize()
    if let array = NSUserDefaults.standardUserDefaults().arrayForKey("ARRAYEMPRESA")! as! [[String]] {
                    return array
    }
    return [String]()
}

UPDATE: I've seen your update code. I want to focus your attention in this method:

func recuperaEmpresas(){
    // Are my data ready to read??? who can say to me this in main thread?? 
    menu = buscaEmp.getEmpresas()
}

So you cant call self.tablaVista.reloadData() until you are pretty sure your data can be exists. To do it you can use a completion handler (click me if you want to know how to build it)

func recuperaEmpresas(url: NSURL,completionHandler: CompletionHandler){
        callMyNetwork() { //do call and after finish do...
           menu = buscaEmp.getEmpresas()
           self.tablaVista.reloadData()
        }
}
Community
  • 1
  • 1
Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133
  • it's not a mistake cause the result is anything like that [["123","456"], ["789","000"]] is array of array – Aris Guimerá May 19 '16 at 10:52
  • Can you add some code about http data fetching and where you set NSUserDefaults after you have these datas? – Alessandro Ornano May 19 '16 at 12:16
  • 1
    Updated (EDITED FOR Alessandro Ornano). Thanks – Aris Guimerá May 19 '16 at 12:34
  • I was reading about completion handler and have some questions (it is really hard for me).1- What is callMyNetwork()? 2- I have to declare typealias CompletionHandler = (success:Bool) -> Void right? 3- When I call the method on viewDidLoad and viewDidAppear I have to send some parameters but don't understand why. – Aris Guimerá May 20 '16 at 07:56
  • Its not necessary to call everywhere your network call method (call my network), for example you can use it in viewDidAppear only and in completion you must do the ui refresh – Alessandro Ornano May 20 '16 at 12:26
  • Don't work, and every time I use it, my app is bugged. I tried it http://stackoverflow.com/questions/30541010/how-to-reload-data-in-a-tableview-from-a-different-viewcontroller-in-swift (is what I want) but dont work – Aris Guimerá May 20 '16 at 13:36
0

Try to put tableVista.reloadData() in your prepareForSegue or unwindToHome function (whichever you are using to go back to second view). If this is not possible, you can always set a bool var which determines if the view is loaded from the first view or the second view and then reload data accordingly.

Hope this helps. :)

bhakti123
  • 833
  • 10
  • 22