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()

    }

}

      

+3


source to share


2 answers


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 in connectionDidFinishLoading

    , 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 in connectionDidFinishLoading

    , so # 1 is the main thing that I think should happen.
+5


source


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()
}

      

+4


source







All Articles