致命错误:刷新表视图时索引超出范围 [英] fatal error: Index out of range when refreshing table view

查看:138
本文介绍了致命错误:刷新表视图时索引超出范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在进行刷新刷新时,我发生了这个奇怪的应用崩溃.

我的代码如下:

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

该应用程序正常运行,即使我下拉刷新也可以正常运行,但是如果长时间下拉刷新,例如下拉几乎撞到屏幕底部,则应用崩溃并提示以下错误:

严重错误:索引超出范围

在线

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

如果我按如下所示打印帖子数和indexPath:

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

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

posts.count = 0

indexPath.row = 2

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

希望我的信息是可以理解的,主要是为了解决问题.

解决方案

您的问题是,您在getData中要做的第一件事是删除self.posts中的所有帖子,但您没有这样做(大概是因为代码是丢失)重新加载表格视图,因此现在数组中的帖子数(0)和表格视图*认为在数组中的帖子数(不为零)不同,所以您会遇到数组边界崩溃的情况.

self.posts.removeAll()之后调用reloadData将解决此问题,但由于表视图重新填充为空,然后重新填充新数据,因此导致闪烁".

由于您没有显示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
    }
}

这样,在拥有新数据之前,您不会操纵后备阵列.

I've this weird app crash when pulling to refresh occurs.

My code goes as it follows:

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

The app runs properly and even when I pull down to refresh, everything runs perfectly, but if do a long pull down to refresh, like pulling down almost hitting the bottom of the screen, the app crashes and prompts the following error:

fatal error: Index out of range

on the line

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

If I print the post count and the indexPath as follows:

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

When I'm pulling down in the normal way, it prints the correct data, but if I pull down like a long pull, through the whole screen if prompts this when it crashes

posts.count = 0

indexPath.row = 2

This kind of thing has never happen to me using the refreshControl the way I'm using here.

Hope my information is understandable, mostly on the long pull to refresh issue.

解决方案

Your problem is that the first thing you do in getData is remove all of the posts from self.posts, but you do not (presumably since code is missing) reload the table view, so now the number of posts in the array (0) and the number of posts that the tableview *thinks is in the array (not zero) is different, so you get an array bounds crash.

Calling reloadData after self.posts.removeAll() would fix the issue but result in the tableview 'flashing' as it redrew empty and then redrew with the new data.

Since you haven't shown the full code for getData I can't provide the exact code you need, but it should be something like:

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

This way you don't manipulate the backing array until you have the new data.

这篇关于致命错误:刷新表视图时索引超出范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆