? ? ?在iOS 中我們經(jīng)常和tableview打交道,這幾天突然想自己去模仿tableview機(jī)制來實(shí)現(xiàn)一個(gè)仿tableview,雖然代碼最后沒有什么用,但是體驗(yàn)了一次思考到實(shí)踐的過程。
? ? tableviewcell的復(fù)用機(jī)制是:創(chuàng)建cell時(shí)給這個(gè)cell一個(gè)id,這個(gè)攜帶有id的cell會被放入緩存,然后再cell滾動的時(shí)候,離開顯示區(qū)域的cell會被回收,新滾動出現(xiàn)的界面會從緩存區(qū)獲取cell,如果沒有則創(chuàng)建新的cell。
ok,那我們開始分析,tableview如何做到復(fù)用cell,cell的一個(gè)id是怎么被使用的。tableview的一個(gè)方法是,dequeueReusableCellWithIdentifier:,這個(gè)是從緩存獲取可復(fù)用的cell,那么tableview就含有一個(gè)存儲可復(fù)用cell的屬性(暫時(shí)定為cacheCells)。cell的初始化方法initWithStyle:reuseIdentifier:這個(gè)方法是給cell設(shè)定id的,那么,cell中也有一個(gè)屬性是id。tableview根據(jù)這個(gè)id來獲取cell,那么cacheCells就是一個(gè)字典。
知道cell的緩存,那如何能做到,回收cell呢?ok,繼續(xù)分析。cell在離開界面時(shí),cell被回收。那么這個(gè)時(shí)候就是檢測cell的frame是否是在scrollview內(nèi)部。用CGRectContainsRect(rect1,cell.frame);來確定,如果在外部,就回收。
那么如何獲取cel放到scrollview中?當(dāng)然也是根據(jù)cell的frame來對比,是否在scrollview的顯示區(qū)域內(nèi),如果是就加入到scrollview中,但是有一點(diǎn),cell還沒創(chuàng)建怎么會有frame?這個(gè)時(shí)候代理的好處就顯現(xiàn)出來了,tableview的代理中有獲取高度和總數(shù)的方法,通過高度計(jì)算出cell的frame很簡單,把所有frame都存儲起來,在試圖滾動的時(shí)候,我們將frame提取出來做對比,如果在視圖顯示區(qū)域,我們就調(diào)用代理獲取cell,而在代理中就有實(shí)現(xiàn)復(fù)用的方法。
ok,貼代碼
https://github.com/dadademao/FYTableview
新修改
在cell多時(shí),之前的代碼發(fā)生了異常情況,cell會被異常回收,檢查代碼時(shí)發(fā)現(xiàn)我一直在回收視圖展示的cell,用dictionary導(dǎo)致覆蓋了之前緩存區(qū)的cell,cell數(shù)量會越來越少,所以及時(shí)做修正,將dictionary改成Set,來保證cell不被無緣無故覆蓋掉。