首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用重新加载数据时,UITableViewCell未从UITableView中删除

使用重新加载数据时,UITableViewCell未从UITableView中删除
EN

Stack Overflow用户
提问于 2016-02-22 16:10:41
回答 3查看 707关注 0票数 0

我使用一个表视图来显示左菜单中的一些类别。选择它时,单元格中的数据将更改为该类别中的课程(“Cursussen”)。

每个单元格包含一个UIImageView和一个UILabel

不久前,我注意到,当您在左边菜单中选择一个课程时,标签将更改为一个类别的标签。那不是一个大问题,但现在我正在努力禁用某些课程,如果没有,它突然成为一个大问题。为了指出一个不可用的课程,我设置了label.enabled = false,这很好,但是我也需要防止用户点击它并导航到一个不可用的课程。为此,我使用tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)检查是否启用了UILabel。如果它被禁用,应用程序将不会导航到该课程。

回到问题上,点击一个不可用的课程(显示正确的图像和标签)将触发didSelectRowAtIndexPath委托,但是当我将Cell排出队列并检查其中的UILabel是否被禁用时,它恰好被启用了,而且label.text并不等于我在应用程序中看到的值。

选择行之前的状态:

选择行后的状态:

cellForRowAtIndexPath方法:

代码语言:javascript
复制
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
    -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("LeftCell", forIndexPath: indexPath)
        let label = cell.contentView.subviews[0] as! UILabel
        let image = cell.contentView.subviews[1] as! UIImageView
        if(selectedCategory.ID > 0 || searchCursusses.count > 0) {
            //Category is selected, load course into cell
            var cursus : Cursus
            if(selectedCategory.ID > 0) {
                cursus = cursusses[indexPath.row] as Cursus
            } else {
                cursus = searchCursusses[indexPath.row] as Cursus
            }
            image.image = self.chooseImage(false, name: cursus.category!.Name)
            label.numberOfLines = 0
            label.text = cursus.name
            label.lineBreakMode = .ByTruncatingTail
            if(defaults.boolForKey("offline-mode")) {
                let realm = try! Realm()
                let videos = realm.objects(DownloadedVideo).filter("video.cursus.ID = %@", cursus.ID)
                if(videos.count > 0) {
                    label.enabled = true
                } else {
                    label.enabled = false
                }
            } else {
                label.textColor = UIColor.blackColor()
            }
            cell.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
            cell.setSelected(false, animated: false)
        } else {
            let category = categories[indexPath.row] as Category
            image.image = self.chooseImage(false, name: category.Name)
            label.numberOfLines = 0
            label.text = category.Name
            label.lineBreakMode = .ByTruncatingTail
            label.textColor = UIColor.blackColor()
            cell.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
        }
        return cell
}

didSelectRowAtIndexPath方法:

代码语言:javascript
复制
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.dequeueReusableCellWithIdentifier( "LeftCell", forIndexPath: indexPath)
    cell.selectionStyle = .None
    if(selectedCategory.ID > 0 || searchCursusses.count > 0) {
        let label = cell.contentView.subviews[0] as! UILabel
        if(!label.enabled) {
            return
        }
        let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
        let resultViewController = storyBoard.instantiateViewControllerWithIdentifier("CursusView") as! CursusViewController
        if(selectedCategory.ID > 0) {
            resultViewController.loadCursus(self.cursusses[indexPath.row], completionHandler: {
                self.presentViewController(resultViewController, animated:true, completion:nil)
            })
        } else {
            resultViewController.loadCursus(self.searchCursusses[indexPath.row], completionHandler: {
                self.presentViewController(resultViewController, animated:true, completion:nil)
            })
        }
    } else {
        let category = categories[indexPath.row] as Category
        cell.setSelected(true, animated: false)
        let label = cell.contentView.subviews[0] as! UILabel
        let image = cell.contentView.subviews[1] as! UIImageView
        if(label.textColor == UIColor.lightGrayColor()) {
            return
        } else {
            image.image = self.chooseImage(true, name: category.Name)
            label.numberOfLines = 0
            label.text = category.Name
            label.textColor = UIColor.whiteColor()
            label.lineBreakMode = .ByTruncatingTail
            cell.backgroundColor = UIColor(red: 45.0/255.0, green: 145.0/255.0, blue: 220.0/255.0, alpha: 1.0)
            self.selectedCategory = category
            self.topBarTitle.text = category.Name
            let realm = try! Realm()
            let cursusses = realm.objects(Cursus).filter("category.ID = %@", selectedCategory.ID)
            for cursus in cursusses {
                self.cursusses.append(cursus)
            }
            let title = self.leftMenuNav.subviews[0] as! UILabel
            let titleImg = self.leftMenuNav.subviews[1] as! UIImageView
            titleImg.image = UIImage(named: "back-icon")
            title.text = "Cursussen"
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.tableView.slideInFromRight(0.5)
                self.tableView.reloadData()
                self.collectionView.crossFade(0.3)
                self.collectionView.reloadData()
            })
        }
    }
}

在调用reloaddata之后,似乎旧的单元格没有被正确清除,导致多个单元格位于同一个IndexPath上。

我在这里不知所措,请帮帮忙!

EN

回答 3

Stack Overflow用户

发布于 2016-02-22 16:14:15

问题是这条线

代码语言:javascript
复制
let cell = tableView.dequeueReusableCellWithIdentifier( "LeftCell", forIndexPath: indexPath)

didSelectRowAtIndexPath函数中,因为它正在创建一个新的单元格(或试图重用一个单元)并损坏表视图单元缓存。

您应该使用cellForRowAtIndexPath函数获取现有的单元格。

票数 1
EN

Stack Overflow用户

发布于 2016-02-22 16:19:18

您的方法有一个问题:didSelectRowAtIndexPath应该查看模型中的数据,而不是视图中的数据。您的代码试图访问cell并检查它的标签等等,这是错误的。相反,您的方法应该访问相同的底层数据源,这些数据源最初是用来制作标签的。

换句话说,而不是写作

代码语言:javascript
复制
let label = cell.contentView.subviews[0] as! UILabel

然后检查标签的启用/禁用状态。

你应该写

代码语言:javascript
复制
cursus = cursusses[indexPath.row] as Cursus

并检查cursus的可用性。

一个普遍的经验法则是,当您看到代码在UITableViewCell之外访问cellForRowAtIndexPath组件时,会变得非常可疑。测试标签的状态几乎是通用的,这表明代码是不正确的。

票数 1
EN

Stack Overflow用户

发布于 2016-02-22 16:56:57

伙计,你做错了。只有tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell才能脱列单元格并设置其内容。

为了防止选择,您应该在func tableView(_ tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath上做出反应,并返回nil,以表示您不想选择任何内容。

主要问题是,您正在编写复杂的方法。很难弄清楚你在做什么,你打算做什么。(will/did)SelectRowAtIndexPath应该只调用一个/两个一些简单的方法,例如:执行一个segue或加载一些数据。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35558419

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档