服务报价 | 域名主机 | 网络营销 | 软件工具| [加入收藏]
 热线电话: #
当前位置: 主页 > 开发教程 > ios开发教程 >

iOS cell重用问题

时间:2016-04-04 21:54来源:未知 作者:最模板 点击:
在做iOS 开发的最常用到的就是tableview,因此最常见的也就是tableview 的重用问题,这次我来介绍一种tableview 的重用的场景 和如何解决这个重用的问题。首先来看一个图片 1C1B4EAB-491F-47

在做iOS 开发的最常用到的就是tableview,因此最常见的也就是tableview 的重用问题,这次我来介绍一种tableview 的重用的场景 和如何解决这个重用的问题。首先来看一个图片


1C1B4EAB-491F-47E1-9F64-88A13FC7B270.png

这是一个播放的音乐的界面,这里可能会涉及到两个明显的问题,(1)一个播放进度条的进度渲染,需要用到定时器去不断的渲染红点的位置,那么需要用到多少个定时器,应该怎么优化呢,(2)第二个就是在滚动tableview 由于cell 重用的影响会导致没有被点击的播放的cell,红点的位置,播放时间 ,还有播放按钮的状态错误。
(1)第一个问题和我之前写的一篇文章的思路很类似http://www.jianshu.com/p/9784a996d187
大概的思路一个定时器去刷新可见cell 的ui ,由于这个场景是只用对一个cell 操作,那么可以记录下这个正在播放的cell 的索引,通过判断这个cell 是否为空,来判断他是否可见,可以看这个代码段

if   let cell : ReAudioListTableViewCell = tableView1.cellForRowAtIndexPath(curIndex) as? ReAudioListTableViewCell
{
}

那么只需在if里面刷新 cell的ui 即可
(2)第二个问题,由于我们只是处理可见cell 的话,那么在滚动的时候还是会导致其中的一个cell 的由于重用的问题,导致他的进度条的状态和音乐播放时间的状态的错乱,
1 导致错误的原因也很简单,先看下,下面的图片


1515D109-B807-4804-B3E2-F805003828DB.png


由于cell 的重用数组是用从不可见cell获取的,那么可见cell刚好获取正在播放的cell,那么状态就变了。
2要怎么防止重用状态错乱
每次滚动tableview都会调用cellforindexpath,只要我们把每个cell的状态通过这个代理方法告诉tableiview 即可。
3 那么用什么来标记cell的状态,
我现在使用 了curIndex,来记录当前选中的cell 的索引,isplay记录当前选中的cell是否在播放,
大致的思路介绍完了来看下代码

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell  = tableView.dequeueReusableCellWithIdentifier("cell") as! ReAudioListTableViewCell
        //记录下来判断是否为可见cell
        cell.tag = indexPath.row

        //加载本地音乐
        let path:String = NSBundle.mainBundle().pathForResource("lj", ofType:"mp3")!
        let dict  = ["path" : path , "time":"64.0" , "size":"1.8" ,"second":"64.0"]

        cell.getAudioDict(dict)

        cell.title.text = "录音" + String(indexPath.row+1) + ".aac"
        if isfirst
        {
            //第一次加载默认不播放状态
           cell.noPlay()
        }
        else
        {
            //当前点击的索引
            if indexPath.row == curIndex.row
            {
                //如果播放设置为播放的状态
                if isPlay == true
                {
                   //记录播放的状态和进度
                    cell.playBtn.selected = true
                    cell.playBar.playProgress(CGFloat(playProgress))
                }
                //如果没有播放显示未播放状态
                else
                {
                   cell.noPlay()
                }
            }
            //不是当前点击说明没有播放
            else{
                cell.noPlay()
            }

        }
        return cell
    }

最后再说说一种场景就是,(1)选择当前的播放的cell,在点一次就需要关闭,(2)或者选择另外一个cell,要暂停前一个,播放当前的这个,思路又是怎样的呢(还是利用的报存当前的索引curIndex)
1 判断curIndex 和 didselect 的index 是否相同,相同的播放 在通过isplay 判断是否正在播放,播放则暂停,暂停则继续播放
2 如果curIndex 和 didselect 的index 不相同,说明是场景2 ,则需要修改判断前一个cell是否在播放,播放则需修改上次状态为暂停,这里需要注意两个点,来看下代码段

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let cell = tableView.cellForRowAtIndexPath(indexPath) as! ReAudioListTableViewCell
        //如果首次播放 curIndex 没有赋值 ,需要特殊处理一下
        if isfirst
        {
            //记录当前选中索引
            //已非第一次选中
            isfirst = false
            //运行定时器
            timeTick = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "playingAction", userInfo: nil, repeats: true)
//            NSRunLoop.currentRunLoop().addTimer(timeTick, forMode: NSRunLoopCommonModes)
            tableView.deselectRowAtIndexPath(indexPath, animated: true)
            cell.startPlay()
           //////////////////////////////////注意
           ////////////curIndex = indexPath 需要写在timeTick.fire() 之前,因为fire() 会让定时器先跑完一次方法,才会执行下面的代码,由于这个curIndex 赋值在定时器方法用到,所以需要先赋值,如果想改变可以将定时器放入队列中

            curIndex = indexPath
            timeTick.fire()
        }
        else
        {
            //如果上次选中和当前选中索引相同,说明用户再次点击正在播放的cell,希望音乐暂停
            if(curIndex.row == indexPath.row)
            {
                //如果正在播放

                if isPlay == true
                {
                    isPlay = false
                    cell.stopPlay()
                    timeTick.invalidate()

                }
                else
                {
                    cell.startPlay()
                    isPlay = true
                    timeTick = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "playingAction", userInfo: nil, repeats: true)
                    NSRunLoop.currentRunLoop().addTimer(timeTick, forMode: NSRunLoopCommonModes)
                    tableView.deselectRowAtIndexPath(indexPath, animated: true)
                    cell.playBtn.selected = true

                    timeTick.fire()
                    curIndex = indexPath
                }
            }
                //点击一个新的cell播放
            else
            {
                //////////////////////////////////注意
                ////////////需要判断lastcell 是否为空,如果lastcell 不可见可能会为空
                if let lastcell : ReAudioListTableViewCell = tableView1.cellForRowAtIndexPath(curIndex) as? ReAudioListTableViewCell {
                    lastcell.stopPlay()
                }

                if RecorderTool.getTool().player.playing {
                    RecorderTool.getTool().player.stop()
                }


                //当前cell 开始播放
                cell.startPlay()
                isPlay = true
                //设置定时器
                timeTick = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "playingAction", userInfo: nil, repeats: true)
                NSRunLoop.currentRunLoop().addTimer(timeTick, forMode: NSRunLoopCommonModes)
                tableView.deselectRowAtIndexPath(indexPath, animated: true)
                curIndex = indexPath
                timeTick.fire()

            }

         }

    }

 



 
(责任编辑:最模板)
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
栏目列表
热点内容