學(xué)iOS的應(yīng)該沒有沒用過tableView的吧,tableView里面會對dequeueReusableCellWithIdentifier申明的cell根據(jù)identifier進(jìn)行復(fù)用,而cell的復(fù)用相信會讓一些初學(xué)者有一些困擾,它是怎么實(shí)現(xiàn)復(fù)用的,為什么我這么寫,cell會變得好亂,完全不是我想要的。
而在平常的需求里面也會遇到一些需要橫向的可循環(huán)使用的視圖的需求
如下圖,

如果每需要一個(gè)就重新創(chuàng)建一個(gè)
view的話,這么多view會占用太多的內(nèi)存了,而且其實(shí)很多view,完全是占著茅坑不拉屎。所以,我們一般都會用復(fù)用其中的view,如果我們實(shí)現(xiàn)了這樣一個(gè)有復(fù)用視圖,對于以后多個(gè)imageView、tableView等就有一個(gè)比較好的處理方法了。
以上就是我寫這個(gè)pageListView的原因, 1.增強(qiáng)對于復(fù)用的理解 2.便于平常項(xiàng)目里面對于一些可重復(fù)使用的view做一個(gè)簡單地集成封裝。
其實(shí)我們要實(shí)現(xiàn)的pageListView復(fù)用的原理和tableView對于cell的復(fù)用的原理基本一致,只是簡單了很多。因?yàn)槲覀兡壳翱紤]的都是一頁一頁的切換。所以不必考慮這個(gè)view的size和滑動(dòng)完之后停留在兩個(gè)view中間的情況。
簡單說一下我們目前的思路,其實(shí)和tableViewCell復(fù)用的機(jī)制類似,創(chuàng)建兩個(gè)池子,一個(gè)放可視區(qū)域的views,另一個(gè)放可復(fù)用views。當(dāng)需要展示一個(gè)view,而復(fù)用池為空時(shí),就創(chuàng)建一個(gè)新的view,并將這個(gè)view放在可視views池,如果一個(gè)view已經(jīng)完全出了可視區(qū)域,就把它放入復(fù)用池,每次加載view的時(shí)候給view設(shè)置一下frame。
上面講了最基本的思路,下面讓我們來實(shí)現(xiàn)看看。
https://github.com/redihd/PageListView
這個(gè)是我實(shí)現(xiàn)一個(gè)可復(fù)用的pageListView的代碼,想看的可以拉下來看一下。
下面我會用我實(shí)現(xiàn)的代碼來做簡單的講解。

因?yàn)橐獙?shí)現(xiàn)的view很簡單,所以我們在.h文件中也沒有太多的屬性與方法,主要就是有個(gè)三個(gè)block來實(shí)現(xiàn)類似tableView的datasource 與delegate。其中loadViewAtIndexBlock 需要兩個(gè)傳入?yún)?shù),會有一個(gè)返回的view,這個(gè)block實(shí)現(xiàn)了類似- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;這個(gè)方法。在接下來我們會細(xì)講這個(gè)block的功能。
再來看.m文件里面的屬性

我們將一些不需要對外暴露的都放在了.m中,其中兩個(gè)屬性
visibleListViewsItems,dequeueViewPool是實(shí)現(xiàn)能夠復(fù)用view的pageView的關(guān)鍵。visibleListViewsItems :這個(gè)可變字典用來存儲可視區(qū)域的視圖及其對應(yīng)的index。dequeueViewPool:這個(gè)可變set用來存儲可復(fù)用的視圖。.m文件中大多數(shù)方法都是設(shè)置frame,位移等,我們這里不談,主要介紹其中幾個(gè)關(guān)鍵方法

loadDequeueViewAndVisibleViewsIfNeeded該方法主要是在scrollview的contentOffset.x變化時(shí),計(jì)算應(yīng)該要在可視視圖字典中的視圖,把舊的可視視圖字典里面的視圖移動(dòng)到可重用視圖池,然后將要新的展示的視圖取出來,加入可視視圖字典。

loadViewAtIndex該方法主要是從我們datasource的block獲取要展示的view,這個(gè)view默認(rèn)是從復(fù)用池即visibleListViewsItems任意取一個(gè)view來當(dāng)做我們將要展示的view,并將其與index加入visibleListViewsItems,如果block提供的view為空,再新建一個(gè)view。然后將原來在view要展示的位置的視圖(如果還有的話)移除,并加入visibleListViewsItems。
基本思路就是這樣了
然后關(guān)于如何使用這個(gè)view

totalPagesCountBlock 這個(gè)block設(shè)置有多少個(gè)view要展示
loadViewAtIndexBlock 這個(gè)block處理可重用的視圖
pageViewClickBlock 這個(gè)block處理點(diǎn)擊事件
個(gè)人比較喜歡用block,所以把delegate和datasource都用block來做了。
最后跑一下,可以看到,即使設(shè)置了60000個(gè),但是cpu和memory都還是很小。

最后,其實(shí)我們現(xiàn)在要實(shí)現(xiàn)這種視圖,用橫向的collectionView來做就好了。但是,寫一個(gè)這種對于個(gè)人理解一些東西的實(shí)現(xiàn)還是有幫助的。接下來可能會把這個(gè)寫的更詳細(xì),功能再多一些。
另外再就是自己用uiview實(shí)現(xiàn)一個(gè)缺一部分功能的scrollView。