UITableViewCell中的UIButton正在被重用

时间:2015-08-23 10:54:12

标签: ios swift uitableview uibutton

我的tableview显示播客数据。所有单元格都可以正常使用,并以正确的顺序显示播客。我添加下载和播放按钮作为每个单元格的子视图。当我向下滚动列表时,将显示意图为未下载的剧集隐藏的播放按钮,并将保存先前发起下载的单元格的数据。例如,如果我点击单元格1中的下载按钮,它将下载正确的剧集,播放按钮将完美地播放该剧集。如果我向下滚动到单元格10,将出现相同的播放按钮,并将从按钮1播放剧集。我的代码出了什么问题?

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
    let cell: PFTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! PFTableViewCell
    if let title = object?["title"] as? String {
        cell.textLabel?.text = title
        let downloadButton = UIButton(type: UIButtonType.Custom)
        downloadButton.frame = CGRectMake(cell.contentView.bounds.width - 100, cell.contentView.bounds.height / 2, 100, 35)
        downloadButton.setTitle("Download", forState: .Normal)
        downloadButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
        downloadButton.tag = indexPath.row
        downloadButton.addTarget(self, action: "downloadEpisode:", forControlEvents: .TouchUpInside)
        cell.addSubview(downloadButton)
        let playButton = UIButton(type: UIButtonType.Custom)
        playButton.frame = CGRectMake(cell.contentView.bounds.width - 100, cell.contentView.bounds.height - 89, 100, 35)
        playButton.setTitle("Play", forState: .Normal)
        playButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
        playButton.tag = indexPath.row
        playButton.addTarget(self, action: "playEpisode:", forControlEvents: .TouchUpInside)
        if let isDownloaded = object?["isDownloaded"] as? String {
            if isDownloaded == "yes" {
                playButton.hidden = false
            } else {
                playButton.hidden = true
            }
        }
        cell.addSubview(playButton)
    }
    return cell
}

编辑:

我也试过了,但它不起作用,仍然每个单元格再创建一个按钮:

     override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
    let cell: PFTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! PFTableViewCell
    if let title = object?["title"] as? String {
        cell.textLabel?.text = title
    }
        if let button = cell.viewWithTag(indexPath.row) {
            print(button)
        } else {
            if let isDownloaded = object?["isDownloaded"] as? String {
                if isDownloaded == "yes" {
                    let downloadButton = UIButton(type: UIButtonType.Custom)
                    downloadButton.frame = CGRectMake(cell.contentView.bounds.width - 100, cell.contentView.bounds.height / 2, 100, 35)
                    downloadButton.setTitle("Play", forState: .Normal)
                    downloadButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
                    downloadButton.tag = indexPath.row
                    downloadButton.addTarget(self, action: "playEpisode:", forControlEvents: .TouchUpInside)
                    cell.addSubview(downloadButton)
                } else {
                    let downloadButton = UIButton(type: UIButtonType.Custom)
                    downloadButton.frame = CGRectMake(cell.contentView.bounds.width - 100, cell.contentView.bounds.height / 2, 100, 35)
                    downloadButton.setTitle("Download", forState: .Normal)
                    downloadButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
                    downloadButton.tag = indexPath.row
                    downloadButton.addTarget(self, action: "downloadEpisode:", forControlEvents: .TouchUpInside)
                    cell.addSubview(downloadButton)
                }
            }
    }

    return cell
}

EDIT2:

添加了下载方法:

        func downloadEpisode(sender: UIButton) {
    print("Downloading..")
    let indexPath = NSIndexPath(forRow: sender.tag, inSection: 0)

    let object = self.objectAtIndexPath(indexPath)
    if let result = object {
    let urlstring = result["downloadURL"] as? String
    if urlstring != nil {
    let episodeURL = NSURL(string: urlstring!)
        downloader.downloadPodcastEpisode(episodeURL!, podcast: result)
        }
    }
}

答案:

虽然所有答案都是正确的,但我决定最后删除按钮下载/播放单元格。非常感谢!

3 个答案:

答案 0 :(得分:1)

问题是您每次都要添加按钮。当您的单元格被重用时,它将有一个按钮。您需要编写代码以确保只创建一次按钮,然后修改现有按钮而不是创建新按钮。

有两种常见方法:

  • 使用viewWithTag检查按钮是否存在(创建按钮并设置其标签,如果没有)
  • 子类UITableViewCell,在初始化程序中创建按钮,并在每次使用单元格时配置按钮。

搜索“uitableviewcell viewwithtag”或“subclass uitableviewcell”应该会提供大量的示例代码,所以我不会在这里重复。

答案 1 :(得分:0)

这是因为在代码中单元格中放置按钮是单向的:一旦按钮被添加到单元格中,它就永远不会被删除或变得不可见。

如果该按钮存在,您需要在else语句中添加if以从已回收的单元格中删除该按钮。

更好的是,将按钮设为"Cell"的永久部分,并在同一if语句中控制其可见性:不添加按钮,使其可见;而不是删除按钮,使其不可见。作为一个额外的好处,这将允许您在界面构建器中设置按钮的视觉外观,并设置一些约束,这将有助于避免"魔术数字"例如代码正文中的100,89和35。

答案 2 :(得分:0)

查看您的代码清楚地知道您已经是UITableViewCell的子类并拥有自定义用户界面,然后在初始化或UITableViewCell xib的{​​{1}}旁边建议添加按钮1}}然后在cell中添加UIButton(通过界面构建​​器)并为新添加的按钮创建xib

现在当重新使用IBOutlet时,您也将拥有该按钮,当重复使用单元格时,您有责任保持其状态正确(意味着更新其UI),对于覆盖cell自定义prepareForReuse类中的方法和单元格的重置UI,在tableViewCell中,您可以根据新数据对象更新UI。