致命错误:刷新表视图时索引超出范围

Iva*_*ino 3 tableview ios pull-to-refresh swift3

当拉到刷新时,我发现了这个奇怪的应用程序崩溃.

我的代码如下:

var posts: [Posts] = []

override func viewDidLoad() {
    super.viewDidLoad()

    // refreshControl -> pull to refresh handler
    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self,
                             action: #selector(Main_TVC.getData),
                             for: UIControlEvents.valueChanged)
    self.refreshControl = refreshControl

    getData()
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return posts.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
                                             for: indexPath) as! PostsTableViewCell

    cell.titleLabel.text = posts[indexPath.row].postTitle
    cell.bodyLabel.text = posts[indexPath.row].postBody

    return cell
}

func getData() {
    self.posts.removeAll()

    // queries the backend and fills the data - sorry for code omission

    refresh()

}


func refresh() {
    self.tableView.reloadData()
    self.refreshControl?.endRefreshing()
}
Run Code Online (Sandbox Code Playgroud)

该应用程序运行正常,即使我下拉刷新,一切运行完美,但如果做一个很长的下拉刷新,如拉下几乎击中屏幕的底部,应用程序崩溃并提示以下错误:

致命错误:索引超出范围

在线上

cell.titleLabel.text = posts [indexPath.row] .postTitle

如果我按如下方式打印帖子计数和indexPath:

print("posts.count =(posts.count)") print("indexPath.row =(indexPath.row)")

当我以正常方式向下拉时,它会打印正确的数据,但是如果我像长拉一样拉下来,如果在崩溃时提示它,则通过整个屏幕

posts.count = 0

indexPath.row = 2

这种事情从未发生在我使用refreshControl的方式,就像我在这里使用的那样.

希望我的信息是可以理解的,主要是长期刷新问题.

Pau*_*w11 9

你的问题是,你做的第一件事getData就是删除所有帖子self.posts,但你没有(大概是因为代码丢失)重新加载表视图,所以现在数组中的帖子数量(0)和数量tableview*认为在数组中的帖子(不是零)是不同的,所以你得到一个数组边界崩溃.

调用reloadDataself.posts.removeAll()会解决问题,但会导致tableview'闪烁',因为它重新呈现为空,然后使用新数据重新绘制.

由于您没有显示完整的代码,因此getData我无法提供您需要的确切代码,但它应该是这样的:

func getData() { 
     fetchPostsWithCompletion() {
         if let tempPosts = dataFromNetwork {
             self.posts = tempPosts
         } else {
             self.posts.removeAll()
         }
         self.refresh()        // Dispatch this on the main queue if your completion handler is not already on the main queue
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,在获得新数据之前,不会操作后备阵列.