Pull to Refresh in Swift does not reload UITableView
I have JSON
mine filling successfully UITableView
but JSON
updating frequently, so I need the ability to update. I followed THIS TUTORIAL to implement pull control for the update. Visually everything seems to be working correctly, but when I call the tableView.reloadData()
table does not reload. However, if I leave ViewController
and go back, the table is updated. Why tableView.reloadData()
does it work in viewDidAppear
and viewWillAppear
but not in my custom function refresh()
?
MainVC.swift file
class MainVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet var tableView: UITableView!
var dataArray: NSArray = NSArray()
@IBOutlet var Controller: UISegmentedControl!
var refreshControl:UIRefreshControl!
func refresh(sender:AnyObject)
{
refreshBegin("Refresh",
refreshEnd: {(x:Int) -> () in
self.tableView .reloadData()
println("Table Reloaded")
self.refreshControl.endRefreshing()
})
}
func refreshBegin(newtext:String, refreshEnd:(Int) -> ()) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
println("refreshing")
sleep(2)
dispatch_async(dispatch_get_main_queue()) {
refreshEnd(0)
}
}
}
override func viewWillAppear(animated: Bool) {
self.tableView .reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.titleView = UIImageView(image: UIImage(named: "logojpg.jpg"))
startConnectionAt("http://www.domain.com/json.php")
refreshControl = UIRefreshControl()
refreshControl.backgroundColor = UIColor.orangeColor()
refreshControl.tintColor = UIColor.whiteColor()
refreshControl.attributedTitle = NSAttributedString(string: "Pull to Refresh")
refreshControl.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
tableView.addSubview(refreshControl)
}
//MARK: JSON Loading
var data: NSMutableData = NSMutableData()
func startConnectionAt(urlPath: String){
var url: NSURL = NSURL(string: urlPath)
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
connection.start()
}
func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
println("Connection failed.\(error.localizedDescription)")
}
func connection(connection: NSURLConnection, didRecieveResponse response: NSURLResponse) {
println("Recieved response")
}
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
self.data = NSMutableData()
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
self.data.appendData(data)
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
var dataAsString: NSString = NSString(data: self.data, encoding: NSUTF8StringEncoding)
var err: NSError
var json: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
var results: NSArray = json["needs"] as NSArray
self.dataArray = results
tableView.reloadData()
println("success")
}
//End loading of JSON
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
return self.dataArray.count;
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell:CustomCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as CustomCell
var rowData: NSDictionary = dataArray[indexPath.row] as NSDictionary
var firstName=rowData["needFirstname"] as String
var descrip=rowData["needDescription"] as String
var poster=rowData["needPoster"] as String
var city=rowData["needCity"] as String
var state=rowData["needState"] as String
var country=rowData["needCountry"] as String
cell.needFirstName.text = firstName
cell.needDescription.text = descrip
cell.needDescription.numberOfLines = 0
cell.needPoster.text = poster
cell.needCity.text = city
cell.needState.text = state
cell.needCountry.text = country
return cell
}
@IBAction func Change(sender: AnyObject) {
if Controller.selectedSegmentIndex == 0 {
startConnectionAt("http://www.domain.com/localJSON.php")
}
else if Controller.selectedSegmentIndex == 1 {
startConnectionAt("http://www.domain.com/intlJSON.php")
}
self.tableView .reloadData()
}
}
source to share
Your last comment is true in my opinion.
During your pull to a function, refresh
you call tableView.reloadData()
, but reloadData()
essentially does not repopulate the elements in the data source (in your case dataArray
). It simply reloads whatever data is currently in the table view data source at the time it is called.
So my recommendation would be to build your function refresh
so that the following happens:
- Initiate a request to your web service.
- When a response is returned (i.e. executed
connectionDidFinishLoading
), parse the JSON results and assign that result to the dataArray instance. You seem to be doing this already inconnectionDidFinishLoading
, so I just think send a request to your webservice. - Call
tableView.reloadData()
to display all new items that have been added since the last time the tableView data was displayed. Again, you are doing this already inconnectionDidFinishLoading
, so # 1 is the main thing that I think should happen.
source to share
Referring to fooobar.com/questions/119876 / ...
Not sure, but perhaps the connection is being made on a different thread if you need to trigger a table update on the main UI thread.
// using Swift trailing closure syntax:
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}