在Swift中拉到刷新而不是重新加载UITableView

时间:2014-08-29 16:26:52

标签: ios json uitableview swift pull-to-refresh

我已成功JSON填充UITableView,但JSON经常更新,因此我需要刷新功能。我跟着THIS TUTORIAL实现了一个pull to refresh控件。在视觉上,似乎一切正常,但当我致电tableView.reloadData()时,表格不会重新加载。但是,如果我离开ViewController并返回,则表格会更新。为什么tableView.reloadData()可以在viewDidAppearviewWillAppear中使用,但不能在我的自定义refresh()函数中使用?

MainVC.swift文件

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

    }

}

2 个答案:

答案 0 :(得分:5)

在我看来,你的最后评论是正确的。

在您转到refresh功能期间,您致电tableView.reloadData(),但reloadData()本身并不会重新填充数据源中的元素(在您的情况下,dataArray })。它只是在调用表视图的数据源时重新加载当前的所有数据。

所以我的建议是构建你的refresh函数,以便发生以下情况:

  1. 向您的网络服务发起请求。
  2. 当响应返回时(即执行connectionDidFinishLoading),解析JSON结果并将该结果分配给dataArray实例。您似乎已经在connectionDidFinishLoading中执行了此操作,因此我只想将请求发送到您的网络服务,我想。
  3. 调用tableView.reloadData()以显示自上次显示tableView数据以来添加的所有新元素。同样,您已经在connectionDidFinishLoading中执行此操作,因此#1是我认为需要发生的主要事情。

答案 1 :(得分:4)

参考https://stackoverflow.com/a/25957339

不确定但可能连接是在不同的线程上运行,如果需要,则需要在主UI线程上运行表更新

// using Swift's trailing closure syntax:
dispatch_async(dispatch_get_main_queue()) {
    self.tableView.reloadData()
}