Swift:如何刷新没有滞后的tableview(UIRefreshControl)

时间:2017-07-06 03:28:45

标签: ios json swift uitableview

用MYSQL数据库中的对象填充我的表视图,使用PHP和JSON到Swift 3.我有一个下拉刷新功能但是当我下拉刷新它在中途滞后一秒然后继续(就像轮子赢了一秒钟一样)。

我如何更新我的tableview更顺畅,因为我猜测,因为我将来向数据库添加更多内容,滞后越大。我目前在我的数据库中有12个对象,所以想象有100多个对象。

在viewDidLoad

// Pull to Refresh
    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)
    if #available(iOS 10.0, *) {
        myTableView.refreshControl = refreshControl
        print("iOS 10")
    } else {
        myTableView.addSubview(refreshControl)
        print("iOS 9 or iOS 8")
    }

然后拉到刷新功能

// Pull to Refresh
func handleRefresh(refreshControl: UIRefreshControl) {

    // Fetching Data for TableView
    retrieveDataFromServer()

    // Stop Refreshing
    refreshControl.endRefreshing()
}

// Retrieving Data from Server
func retrieveDataFromServer() {

    // Loading Data from File Manager
    loadData()

    let getDataURL = "http://example.com/receiving.php"
    let url: NSURL = NSURL(string: getDataURL)!

    do {
        let data: Data = try Data(contentsOf: url as URL)
        let jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray

        // Clear the arrays
        self.followedArray = [Blog]()
        self.mainArray = [Blog]()

        // Looping through jsonArray
        for jsonObject in jsonArray {

            if let blog = Blog(jsonObject:jsonObject as! [String : Any]) {

                // Check if Identifiers Match
                if followedIdentifiers.contains(blog.blogID) {
                    self.followedArray.append(blog)
                } else {
                    self.mainArray.append(blog)
                }
            }
        }
    } catch {
        print("Error: (Retrieving Data)")
    }
    myTableView.reloadData()
}

5 个答案:

答案 0 :(得分:1)

请参阅以下位置的Apple示例代码:

http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html

一些建议:

不要在cellForRowAtIndexPath:method'处显示数据,因为此时单元格尚未显示。尝试在UITableView的委托中使用tableView:willDisplayCell:forRowAtIndexPath:方法。

重新使用单个实例的单元格/页眉/页脚,即使您需要显示更多内容。

如果需要任何具体内容,请告诉我。

答案 1 :(得分:1)

    Spinner.isHidden = false
    Spinner.startAnimating()
    DispatchQueue.global(qos: .background).async {
       loadData()

    let getDataURL = "http://example.com/receiving.php"
    let url: NSURL = NSURL(string: getDataURL)!

    do {
        let data: Data = try Data(contentsOf: url as URL)
        let jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray

        // Clear the arrays
        self.followedArray = [Blog]()
        self.mainArray = [Blog]()

        // Looping through jsonArray
        for jsonObject in jsonArray {

            if let blog = Blog(jsonObject:jsonObject as! [String : Any]) {

                // Check if Identifiers Match
                if followedIdentifiers.contains(blog.blogID) {
                    self.followedArray.append(blog)
                } else {
                    self.mainArray.append(blog)
                }
            }
        }
    } catch {
        print("Error: (Retrieving Data)")
    }

        DispatchQueue.main.async
        {

            myTableView.reloadData()
            self.Spinner.startAnimating()
            self.Spinner.isHidden = true
        }
    }

答案 2 :(得分:1)

我的猜测是你的retrieveDataFromServer()阻塞了主线程,因此造成了延迟。尝试将其包装在异步块中

// Pull to Refresh
func handleRefresh(refreshControl: UIRefreshControl) {

    // Fetching Data for TableView
    retrieveDataFromServer { [weak refreshControl] in
        // This block will run once retrieveDataFromServer() is completed

        // Reload data
        myTableView.reloadData()

        // Stop Refreshing
        refreshControl?.endRefreshing()
    }
}

// Retrieving Data from Server
func retrieveDataFromServer(completion: (() -> Void)?) {

    // Loading Data from File Manager
    loadData()

    let getDataURL = "http://example.com/receiving.php"
    let url: NSURL = NSURL(string: getDataURL)!

    do {
        let data: Data = try Data(contentsOf: url as URL)
        let jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray

        // Clear the arrays
        self.followedArray = [Blog]()
        self.mainArray = [Blog]()

        // Looping through jsonArray
        for jsonObject in jsonArray {

            if let blog = Blog(jsonObject:jsonObject as! [String : Any]) {

                // Check if Identifiers Match
                if followedIdentifiers.contains(blog.blogID) {
                    self.followedArray.append(blog)
                } else {
                    self.mainArray.append(blog)
                }
            }
        }
    } catch {
        print("Error: (Retrieving Data)")
    }

    // Calls completion block when finished
    completion?()
}

答案 3 :(得分:1)

我认为您遇到的延迟是由于网络请求在主线程上同步执行所致:

let data: Data = try Data(contentsOf: url as URL)

网络请求很慢,几乎可以肯定是在主线程上完成的。这里的解决方案是将网络调用移动到后台线程,这样主(UI)线程就不会被阻塞(滞后)。

那你怎么做的?那是一个很大的问题,有许多不同的答案。

我强烈建议您花些时间学习Swift中的多线程编程(也称为并发)。通过这个Ray Wenderlich tutorial应该会给你一个很好的基础。

然后,了解用于在iOS应用中执行异步网络请求的URLSession可能是一个好主意。 Ray Wenderlich有一个很棒的starter tutorial

最后......这是一个快速而肮脏的解决方案。它" hacky"你可能不应该使用它,但它可能会解决你的滞后问题:

func retrieveDataFromServer() {

    // Loading Data from File Manager
    loadData()

    let getDataURL = "http://example.com/receiving.php"
    let url: NSURL = NSURL(string: getDataURL)!

    // Move to a background queue to fetch and process data from network.
    DispatchQueue.global().async {

        // Don't touch anything related to the UI here.
        do {
            let data: Data = try Data(contentsOf: url as URL)
            let jsonArray = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! NSMutableArray

            // Create new temp arrays to process json
            var tempFollowedArray = [Blog]()
            var tempMainArray = [Blog]()

            // Looping through jsonArray
            for jsonObject in jsonArray {

                if let blog = Blog(jsonObject:jsonObject as! [String : Any]) {

                    // Check if Identifiers Match
                    if self.followedIdentifiers.contains(blog.blogID) {
                        tempFollowedArray.append(blog)
                    } else {
                        tempMainArray.append(blog)
                    }
                }
            }

            // Jump back to main (UI) thread to update results
            DispatchQueue.main.async {
                print("success")
                self.followedArray = tempFollowedArray
                self.mainArray = tempMainArray

                self.myTableView.reloadData()
            }
        } catch {
            DispatchQueue.main.async {
                print("Error: (Retrieving Data)")
                // This reload is probably not necessary, but it was
                // in your original code so I included it.
                self.myTableView.reloadData()
            }
        }
    }
}

答案 4 :(得分:0)

尝试一下:

$chart = "{
  type: 'bar',
  data: {
    labels: ['January', 'February', 'March', 'April', 'May'],
    datasets: [{
      label: 'Dogs',
      data: [ 50, 60, 70, 180, 190 ]
    }, {
      label: 'Cats',
      data: [ 100, 200, 300, 400, 500 ]
    }]
  }
}";

$encoded = urlencode($chart);
$imageUrl = "https://quickchart.io/chart?c=" . $encoded;

// Embed $imageUrl in your email