Swift 如何维护对tableview单元格的引用?

Swift 如何维护对tableview单元格的引用?,swift,uitableview,Swift,Uitableview,我已经建立了一个基本的媒体播放器应用程序。 我有一个表格视图,其中列出了播客。 在行项目中,我列出了播客标题。 我还使用detailTextLabel列出当前播放时间的倒计时 一切正常,但当我滚动tableView时,单元格被重新加载,我无法再更新时间 如何保留单元格的引用,以便即使在滚动后也可以更新单元格文本 以下是相关的代码片段 var myCell = UITableViewCell() func tableView(tableView: UITableView, cellForRowA

我已经建立了一个基本的媒体播放器应用程序。 我有一个表格视图,其中列出了播客。 在行项目中,我列出了播客标题。 我还使用detailTextLabel列出当前播放时间的倒计时

一切正常,但当我滚动tableView时,单元格被重新加载,我无法再更新时间

如何保留单元格的引用,以便即使在滚动后也可以更新单元格文本

以下是相关的代码片段

var myCell = UITableViewCell()

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")

    .... cell code

    return cell
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    myMP.nowPlayingItem = qryPodcasts.items![indexPath.row]
    if myMP.playbackState != MPMusicPlaybackState.Playing {
       myMP.play()
    }

    // Grab a reference to the selected item
    // for displaying elapsed time
    myCell = tableView.cellForRowAtIndexPath(indexPath)!
}

func startTimer(){
    myTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(View_Podcast_List.updateTimer), userInfo: nil, repeats: true)
}
func stoptimer(){
    myTimer.invalidate()
}
func updateTimer(){
    let nowPlayingItemDuration =  myMP.nowPlayingItem?.valueForProperty(MPMediaItemPropertyPlaybackDuration) as! Double
    let remainingTime = nowPlayingItemDuration - myMP.currentPlaybackTime ;

    myCell.detailTextLabel?.text = CommonFuncs.secondsToTime(Int(remainingTime))
}

有两种方法可以继续执行此操作: 第一种是标签方法: 在您的cellForRow中,为单元格指定标记:

MyCell.tag = indexPath.row
在didSelect中选择项时,将indexPath.row存储在属性中。 现在在updateTimer方法中,使用viewWithTag(indexPath.row)提取单元格,它将为您提供单元格,然后更新该单元格上的计时器

第二种方法: 在didSelect中,选中时在属性中存储indexPath.row。然后在cellForRow中,如果indexPath.row等于didSelect中的select属性,则调用实际返回文本的方法updateTimer(在这种情况下,您可能需要更新您的方法)


有两种方法可以继续执行此操作: 第一种是标签方法: 在您的cellForRow中,为单元格指定标记:

MyCell.tag = indexPath.row
在didSelect中选择项时,将indexPath.row存储在属性中。 现在在updateTimer方法中,使用viewWithTag(indexPath.row)提取单元格,它将为您提供单元格,然后更新该单元格上的计时器

第二种方法: 在didSelect中,选中时在属性中存储indexPath.row。然后在cellForRow中,如果indexPath.row等于didSelect中的select属性,则调用实际返回文本的方法updateTimer(在这种情况下,您可能需要更新您的方法)


您可以在计时器回调本身中调用cellforrowatinexpath。然后有两种可能:cellforrowatinexpath返回nil,因此它不在屏幕上,因此无需执行任何操作。或者它返回的不是nil,然后更新它

确保在cellForRowAtIndexPath委托方法中设置正确的时间,以防当行不在屏幕上时错过一些更新


试图保留对单元格的引用是行不通的。它可以防止单元被解除分配,但不会阻止它被重新用于其他单元

您可以在计时器回调本身中调用cellforrowatinexpath。然后有两种可能:cellforrowatinexpath返回nil,因此它不在屏幕上,因此无需执行任何操作。或者它返回的不是nil,然后更新它

weak var myCell: UITableViewCell?

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")

    .... cell code

    if tableView.indexPathForSelectedRow == indexPath {
        myCell = cell;
    }

    return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    myMP.nowPlayingItem = qryPodcasts.items![indexPath.row]
    if myMP.playbackState != MPMusicPlaybackState.Playing {
       myMP.play()
    }

    // Grab a reference to the selected item
    // for displaying elapsed time
    myCell = tableView.cellForRowAtIndexPath(indexPath)!
}

func startTimer(){
    myTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(View_Podcast_List.updateTimer), userInfo: nil, repeats: true)
}
func stoptimer(){
    myTimer.invalidate()
}

func updateTimer(){
    guard myCell != nil else { return }
    let nowPlayingItemDuration =  myMP.nowPlayingItem?.valueForProperty(MPMediaItemPropertyPlaybackDuration) as! Double
    let remainingTime = nowPlayingItemDuration - myMP.currentPlaybackTime ;

    myCell?.detailTextLabel?.text = CommonFuncs.secondsToTime(Int(remainingTime))
}
确保在cellForRowAtIndexPath委托方法中设置正确的时间,以防当行不在屏幕上时错过一些更新


试图保留对单元格的引用是行不通的。它可以防止单元被解除分配,但不会阻止它被重新用于其他单元

一种解决方案是保留一个包含每个单元格状态的列表,您不能保留对该单元格的引用,因为它是自动重用的。这样,每次重复使用单元格时,就会调用
cellforrowatinexpath
,您可以恢复单元格的状态并恢复
NSTimer
,etcOne解决方案可以保留一个包含每个单元格状态的列表,您无法保留对单元格的引用,因为它是自动重复使用的。这样,每次重复使用单元格时,就会调用
cellforrowatinexpath
,您可以恢复单元格的状态并恢复
NSTimer
,etcArun-我选择了标记方法,只需对您的建议进行一次更改。我使用的不是“indexPath.row”,而是“indexPath”。var selectedRow=NSIndexPath()然后在cellForRow:cell.tag=indexPath.row中,然后在didSelect:selectedRow=indexPath中,然后在UpdateTime:let myCell=tableView.cellForRowAtIndexPath(selectedRow)中是的。您可以根据需要更改实现。我只是给出了如何实现它的基本流程。使用标签很糟糕,但是给单元格添加标签真的很糟糕。最简单的解决方案是使用静态单元格——只需创建单元格实例并始终为给定索引返回它——并且永远不要重用它。@Sulthan——如何创建静态单元格?你能给我指一个Swift样本吗?阿伦-我选择了标记方法,只需对你的建议做一个更改。我使用的不是“indexPath.row”,而是“indexPath”。var selectedRow=NSIndexPath()然后在cellForRow:cell.tag=indexPath.row中,然后在didSelect:selectedRow=indexPath中,然后在UpdateTime:let myCell=tableView.cellForRowAtIndexPath(selectedRow)中是的。您可以根据需要更改实现。我只是给出了如何实现它的基本流程。使用标签很糟糕,但是给单元格添加标签真的很糟糕。最简单的解决方案是使用静态单元格——只需创建单元格实例并始终为给定索引返回它——并且永远不要重用它。@Sulthan——如何创建静态单元格?你能给我指一个Swift样本吗?我实际上使用的是第二种方法,因为标签不太好用。所以我按照你的建议去做——在计时器更新中使用cellforrowatinedexpath并检查nil……实际上我使用的是第二种方法,因为标记工作得不好。所以我按照你的建议去做-在计时器更新中检查cellForRowAtIndexPath并检查nil。。。
weak var myCell: UITableViewCell?

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")

    .... cell code

    if tableView.indexPathForSelectedRow == indexPath {
        myCell = cell;
    }

    return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    myMP.nowPlayingItem = qryPodcasts.items![indexPath.row]
    if myMP.playbackState != MPMusicPlaybackState.Playing {
       myMP.play()
    }

    // Grab a reference to the selected item
    // for displaying elapsed time
    myCell = tableView.cellForRowAtIndexPath(indexPath)!
}

func startTimer(){
    myTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(View_Podcast_List.updateTimer), userInfo: nil, repeats: true)
}
func stoptimer(){
    myTimer.invalidate()
}

func updateTimer(){
    guard myCell != nil else { return }
    let nowPlayingItemDuration =  myMP.nowPlayingItem?.valueForProperty(MPMediaItemPropertyPlaybackDuration) as! Double
    let remainingTime = nowPlayingItemDuration - myMP.currentPlaybackTime ;

    myCell?.detailTextLabel?.text = CommonFuncs.secondsToTime(Int(remainingTime))
}