0

I have a UITableViewController that contains a static UITableView from which you can request quotes and buy or sell a stock. I handle all communications to the backend in a separate ServerCommunicator class. When a request completes, the ServerCommunicator calls the delegate (the tableViewController) which updates the fields in the tableView.

In the main queue, I call tableView.reloadData and display the fields.

The problem is that the fields display immediately but show stale values. When I select a row by clicking on it, however, value is updated.

What am I doing wrong?

class AddStockTableViewController: UITableViewController, ServerCommunicatorDelegate {

………..

override func viewDidLoad() {
    super.viewDidLoad()
    nameLabel.hidden = true
    symbolLabel.hidden = true
    quoteLabel.hidden = true
    changeLabel.hidden = true
     ….….   

}

@IBAction func getQuoteAction(sender: UIButton) {

    if let symbol = getQuoteTextField.text {
        serverCommunicator.updateQuote(symbol, delegate: self)
    }
}

func didCompleteRequest(data : NSData)
{
    quote = parseQuote(data)

    self.symbolLabel.text = "(\(self.quote.symbol))"
    self.nameLabel.text = self.quote.name
    self.quoteLabel.text = "\(self.quote.currentPrice)"
    self.changeLabel.text = “\(self.quote.change)"

    ……. 


    dispatch_async(dispatch_get_main_queue(), {

        self.tableView.reloadData()
        self.nameLabel.hidden = false
        self.symbolLabel.hidden = false
        self.quoteLabel.hidden = false
        ………
     }

   }


class ServerCommunicator
{
    func sendRequest(requestURL : String, requestString : String, delegate : ServerCommunicatorDelegate)
    {
       if let requestData = requestString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false){
          let request = NSMutableURLRequest(URL: NSURL(string: requestURL)!)
          request.HTTPMethod = "POST"

          let urlSession = NSURLSession.sharedSession()
          let task = urlSession.uploadTaskWithRequest(request, fromData: requestData, completionHandler: {(data, response, error) -> Void in

            if error != nil {
                println(error.localizedDescription)
            }
            else {
                delegate.didCompleteRequest(data)
            }
        })
        task.resume()

    } else {
        print("Could not encode requestString to data")
    }
  }
 …….
}   
cerphin
  • 41
  • 7
  • Which thread is ServerCommunicator running on? – SwiftArchitect Jul 19 '15 at 06:18
  • ServerCommunicator runs on the main thread but the completion handler for uploadTaskWithRequest runs on another thread. The completion handler calls didCompleteRequest when then queues tableView.reloadData on the main thread. – cerphin Jul 20 '15 at 03:09
  • Anyone have an idea? – cerphin Jul 23 '15 at 17:51
  • It appears that your data is not available (i.e.) updated when you invoke `reloadData`. There seem to be a few class variables in your view controller. Do those need to be there, rather than at the `UITableViewCell` level? Also, have you verified that the `cellForRowAtIndexPath` triggered by the `reloadData` returns proper values (not cached, old, stale values). It seems to be a reasonable assumption. – SwiftArchitect Jul 23 '15 at 19:01
  • How did you eventually solve your issue? – SwiftArchitect Jan 31 '16 at 01:30

1 Answers1

0

There is no such thing as Static TableView Update. All updates are supposed to occur through a cell change, and such a change shall be triggered by some kind of table view or table view cell refresh.

An update not showing up in a UITableViewCell indicate that the cell is cached and not reloading fresh data.

reloadData in the UITableView triggers reloading all table view cells. Make certain that cellForRowAtIndexPath returns fresh data, and that dequeueReusableCellWithIdentifier uses proper id.

Finally, reloading all cells if you change a single one is not best practice. Is it possible to refresh a single UITableViewCell in a UITableView? Yes it is.

Community
  • 1
  • 1
SwiftArchitect
  • 47,376
  • 28
  • 140
  • 179
  • Sorry, may be poor choice of words on my part. I meant that I am using static cells instead of dynamic prototypes. Therefore, I don't implement methods such as cellForRowAtIndexPath. – cerphin Jul 24 '15 at 06:14
  • Oh, then the answer is easy. Going from static cells to dynamic cells is a snap. Click that checkbox in IB, and implement `cellForRowAtIndexPath`, returning dynamic cells you actually control. Then apply my response. You can be done in 10 mins flat! – SwiftArchitect Jul 24 '15 at 20:38