你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 詳解iOS 滾動視圖的復用問題處理方案

詳解iOS 滾動視圖的復用問題處理方案

編輯:IOS開發綜合

LazyScroll是什麼

LazyScrollView 承繼自ScrollView,目的是處理異構(與TableView的同構比照)滾動視圖的復用回收問題。它可以支持跨View層的復用,用易用方式來生成一個高功能的滾動視圖。

為什麼要用LazyScrollView

我們在做首頁的時分,往往展現的東西會很多,隨著View數量逐步收縮,沒有一套復用回收機制的ScrollView曾經影響到功能了,迫切需求處置對ScrollView中View的復用和回收。運用TableView只能用來處理同類Cell的展現,但是在實踐的場景中在ScrollView外面,View的品種往往會比擬多,所以運用TableView不合適我們的場景。
而UICollectionView自身的規劃和復用回收機制不夠靈敏,用起來也較為繁瑣。所以降生了LazyScrollView去處理這個問題。這也是天貓IOS客戶端的首頁落中央案。

LazyScroll運用

LazyScrollView的運用和TableView很像,不過多了一個需求完成的辦法:前往對應index的View 絕對LazyScrollView的相對坐標。

完成LazyScrollViewDatasource

相似TableView的用法,我們需求運用方完成LazyScrollViewDatasource的Delegate。

@protocol TMMuiLazyScrollViewDataSource <NSObject>
@required
//ScrollView展現item個數
- (NSUInteger)numberOfItemInScrollView:(TMMuiLazyScrollView *)scrollView;
//要求依據index直接前往RectModel
- (TMMuiRectModel *)scrollView:(TMMuiLazyScrollView *)scrollView rectModelAtIndex:(NSUInteger)index;
//前往下標所對應的view
- (UIView *)scrollView:(TMMuiLazyScrollView *)scrollView itemByMuiID:(NSString *)muiID;

LazyScrollView的中心是在初始形態就得知一切View應該顯示的地位。第一個辦法很復雜,獲取LazyScrollView中item的個數。第二個辦法需求依照Index前往TMMuiRectModel ,它會攜帶對應index的View 絕對LazyScrollView的相對坐標。

這裡呈現了一個TMMuiRectModel ,這是個什麼東西呢?我們看一下代碼:

@interface TMMuiRectModel:NSObject
//轉換後的相對值rect
@property (nonatomic,assign) CGRect absRect;
//業務下標
@property (nonatomic,copy) NSString *muiID;

這裡有兩個屬性,absRect是LazyScroll中的View絕對LazyScrollView的相對坐標,muiID是這個View在LazyScrollView中獨一的標識符,可賦值也可不賦值。

第三個辦法,前往View。

@interface UIView(TMMui)

//索引過的標識,在LazyScrollView范圍內獨一
@property (nonatomic, copy) NSString *muiID;
//重用的ID
@property (nonatomic, copy) NSString *reuseIdentifier;

首先,我們在UIView之外加了一個Category,這個category可以讓View攜帶muiID和reuseIdentifier,關於前往的View來說,只需求在乎對View的reuseIdentifier賦值,muiID的賦值會在lazyScrollView中處置掉。reuseIdentifier相反的View會被復用,假如這個View的reuseIdentifier是nil或許空字符串,則不會被復用。

LazyScrollView外部原理剖析

首先來看一個復雜的案例:

依據DataSource獲取一切的TMMuiRectModel

依據DataSource的Delegate,拿到一切的View應該被顯示的地位。這一步,中心是拿到的地位是確定的。依據Demo,我們察看從 0/1 - 2/3 之間這些View,這個時分LazyScrollView拿到的Rect如下:

Index 標號(MUIID) Rect 0 0/0 origin = (x = 25, y = 15), size = (width = 156, height = 150 1 0/1 origin = (x = 194, y = 15), size = (width = 156, height = 150) 2 0/2 origin = (x = 25, y = 180), size = (width = 156, height = 150) 3 0/3 origin = (x = 194, y = 180), size = (width = 156, height = 150 4 1/0 origin = (x = 5, y = 360), size = (width = 177.5, height = 150) 5 1/1 origin = (x = 192.5, y = 426), size = (width = 84, height = 84) 6 1/2 origin = (x = 192.5, y = 360), size = (width = 177.5, height = 56) 7 1/3 origin = (x = 286.5, y = 426), size = (width = 83.5, height = 84) 8 2/0 origin = (x = 25, y = 530), size = (width = 325, height = 150) 9 2/1 origin = (x = 25, y = 695), size = (width = 325, height = 150) 10 2/2 origin = (x = 25, y = 860), size = (width = 325, height = 150)

排序

拿到了這些地位之後,接上去做的事情就是排序。排序生成的索引會有兩個:依據頂邊(y)升序排序的索引和依據底邊(y+height)降序排序的索引。

依據頂邊(y)升序排序的索引

Index 標號(MUIID) Rect 0 0/0 origin = (x = 25, y = 15), size = (width = 156, height = 150 1 0/1 origin = (x = 194, y = 15), size = (width = 156, height = 150) 2 0/2 origin = (x = 25, y = 180), size = (width = 156, height = 150) 3 0/3 origin = (x = 194, y = 180), size = (width = 156, height = 150 4 1/0 origin = (x = 5, y = 360), size = (width = 177.5, height = 150) 5 1/1 origin = (x = 192.5, y = 360), size = (width = 177.5, height = 56) 6 1/2 origin = (x = 192.5, y = 360), size = (width = 177.5, height = 56) 7 1/3 origin = (x = 286.5, y = 426), size = (width = 83.5, height = 84) 8 2/0 origin = (x = 25, y = 530), size = (width = 325, height = 150) 9 2/1 origin = (x = 25, y = 695), size = (width = 325, height = 150) 10 2/2 origin = (x = 25, y = 860), size = (width = 325, height = 150)

依據底邊(y+height)降序排序的索引

Index 標號(MUIID) Rect 0 2/2 origin = (x = 25, y = 860), size = (width = 325, height = 150) 1 2/1 origin = (x = 25, y = 695), size = (width = 325, height = 150) 2 2/0 origin = (x = 25, y = 530), size = (width = 325, height = 150) 3 1/0 origin = (x = 5, y = 360), size = (width = 177.5, height = 150) 4 1/2 origin = (x = 192.5, y = 360), size = (width = 177.5, height = 56) 5 1/3 origin = (x = 286.5, y = 426), size = (width = 83.5, height = 84) 6 1/1 origin = (x = 192.5, y = 426), size = (width = 84, height = 84) 7 0/2 origin = (x = 25, y = 180), size = (width = 156, height = 150) 8 0/3 origin = (x = 194, y = 180), size = (width = 156, height = 150 9 0/0 origin = (x = 25, y = 15), size = (width = 156, height = 150 10 0/1 origin = (x = 194, y = 15), size = (width = 156, height = 150)

查找

前兩步是在執行完reload,在視圖還沒有生成的時分就開端做了,而接上去的步驟在要生成視圖(初始化或滾動的時分)才會去做。

我們設定了Buffer為上下各20,滾動超越20個像素後才會指定查找視圖並顯示的舉措。舉個例子,如下圖,紅圈是應該顯示的區域。

如上圖所示,如今已知的是紅圈頂邊y是242,底邊y是949,加上緩沖區Buffer,應該是找222 - 969 之間的View。我們要做的是,找究竟邊y小於969的Model和頂邊y大於222的Model,取交集,就是我們要顯示的View。

采用的辦法為二分查找,在依據頂邊升序排序的索引中找949,找到的index為0(MUIID為2/2),我們運用一個Set,把依據頂邊排序中index >= 0 的元素先放在這裡。獲取的Set中包括的muiID為 0/0,0/1,0/2,0/3,1/0,1/1,1/2,1/3,2/0,2/1,2/2。

依據底邊排序的索引中找222,找到的index為2,我們把index >= 2的元素放在另一個Set,獲取的Set中包括的muiID為0/2,0/3,1/0,1/1,1/2,1/3,2/0,2/1,2/2

兩個Set取交集,失掉的就是我們的ResultSet,這外面都是我們要顯示View的Model,它們的muiID是0/2,0/3,1/0,1/1,1/2,1/3,2/0,2/1,2/2。

回收、復用、生成

我們知道了應該顯示哪些View,但是我們之後做的第一步是把不需求顯示的View參加到復用池中。LazyScroll可以取到以後顯示了的View,拿以後顯示的View的muiID和將要顯示view的Model的muiID做比照,可以知道以後顯示的View哪些應該被回收。

LazyScrollView中有一個Dictionary,key是reuseIdentifier,Value是對應reuseIdentifier被回收的View,當LazyScrollView得知這個View不該再呈現了,會把View放在這裡,並且把這個View hidden掉。

然後,用LazyScrollView會去調用datasource。

- (UIView *)scrollView:(TMMuiLazyScrollView *)scrollView itemByMuiID:(NSString *)muiID;

復用還是不復用,是由datasource決議的。假如要復用,需求datasource辦法內調用,即:

- (UIView *)dequeueReusableItemWithIdentifier:(NSString *)identifier

獲取復用的View,這個辦法取出來的View就是在上一段所說的Dictionary中拿的。
最後我們看一下LazyScrollView的運用流程:找到一切View將要顯示的地位 – 排序 – 查找應該顯示的View – 回收 – 創立/復用。

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支持本站。

【詳解iOS 滾動視圖的復用問題處理方案】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved