iOS:如何復(fù)用兩個(gè)view實(shí)現(xiàn)可無(wú)限滾動(dòng)的全屏頁(yè)面

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

headTabbarWithViews.gif

如果每需要一個(gè)就重新創(chuàng)建一個(gè)view的話,這么多view會(huì)占用太多的內(nèi)存了,而且其實(shí)很多view,完全是占著茅坑不拉屎。所以,我們一般都會(huì)用復(fù)用其中的view,如果我們實(shí)現(xiàn)了這樣一個(gè)有復(fù)用視圖,對(duì)于以后多個(gè)imageView、tableView等就有一個(gè)比較好的處理方法了。

以上就是我寫(xiě)這個(gè)pageListView的原因, 1.增強(qiáng)對(duì)于復(fù)用的理解 2.便于平常項(xiàng)目里面對(duì)于一些可重復(fù)使用的view做一個(gè)簡(jiǎn)單地集成封裝。

其實(shí)我們要實(shí)現(xiàn)的pageListView復(fù)用的原理和tableView對(duì)于cell的復(fù)用的原理基本一致,只是簡(jiǎn)單了很多。因?yàn)槲覀兡壳翱紤]的都是一頁(yè)一頁(yè)的切換。所以不必考慮這個(gè)viewsize和滑動(dòng)完之后停留在兩個(gè)view中間的情況。

簡(jiǎn)單說(shuō)一下我們目前的思路,其實(shí)和tableViewCell復(fù)用的機(jī)制類(lèi)似,創(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
上面講了最基本的思路,下面讓我們來(lái)實(shí)現(xiàn)看看。

https://github.com/redihd/PageListView
這個(gè)是我實(shí)現(xiàn)一個(gè)可復(fù)用的pageListView的代碼,想看的可以拉下來(lái)看一下。
下面我會(huì)用我實(shí)現(xiàn)的代碼來(lái)做簡(jiǎn)單的講解。

pageView.h

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

pageview.m頭

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

loadDequeueViewAndVisibleViewsIfNeeded.png

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

loadViewAtIndex

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

基本思路就是這樣了

然后關(guān)于如何使用這個(gè)view

initPageView.png

totalPagesCountBlock 這個(gè)block設(shè)置有多少個(gè)view要展示
loadViewAtIndexBlock 這個(gè)block處理可重用的視圖
pageViewClickBlock 這個(gè)block處理點(diǎn)擊事件
個(gè)人比較喜歡用block,所以把delegate和datasource都用block來(lái)做了。

最后跑一下,可以看到,即使設(shè)置了60000個(gè),但是cpu和memory都還是很小。


run

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,667評(píng)論 30 472
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,842評(píng)論 4 61
  • ①時(shí)間 你為旅行預(yù)備的時(shí)間是幾天?幾個(gè)月? 對(duì)于那些一言不合就任性長(zhǎng)期旅行的土豪來(lái)說(shuō),時(shí)間就...
    熱鬧且孤獨(dú)閱讀 962評(píng)論 0 12
  • 我不喜歡習(xí)慣二字,但是更多的時(shí)候確是用習(xí)慣二字來(lái)隱飾無(wú)奈二字。 而我卻在不停的使用著習(xí)慣二字
    翦夢(mèng)閱讀 315評(píng)論 15 18

友情鏈接更多精彩內(nèi)容