ios開發ui篇—uitableviewcell的效能問題
一、uitableviewcell的一些介紹
uitableview的每一行都是乙個uitableviewcell,通過datasource的 tableview:cellforrowatindexpath:方法來初始化每⼀行
uitableviewcell內部有個預設的子檢視:contentview,contentview是uitableviewcell所顯示內容的父檢視,可顯示一些輔助指示檢視
輔助指示檢視
的作⽤是顯示乙個表示動作的圖示,可以通過設定
uitableviewcell
的 accessorytype
來顯示,預設是
uitableviewcellaccessorynone(
不顯⽰示輔助指⽰示檢視
), 其他值如下:
uitableviewcellaccessorydisclosureindicator
uitableviewcellaccessorydetaildisclosurebutton
uitableviewcellaccessorycheckmark
還可以通過cell的accessoryview屬性來自定義輔助指示檢視(⽐如往右邊放乙個開關)
二、問題
cell的工作:在程式執行的時候,能看到多少條,它就建立多少條資料,如果檢視滾動那麼再建立新顯示的內容。(系統自動呼叫)。即當乙個cell出現在視野範圍內的時候,就會呼叫建立乙個cell。這樣的邏輯看上去沒有什麼問題,但是真的沒有任何問題嗎?
當建立呼叫的時候,我們使用nslog列印訊息,並列印建立的cell的位址。我們發現如果資料量非常大,使用者在短時間內來回滾動的話,那麼會建立大量的cell,一直開闢空間,且如果是往回滾,通過列印位址,我們會發現它並沒有重用之前已經建立的cell,而是重新建立,開闢新的儲存空間。
那有沒有什麼好的解決辦法呢?
三、cell的重用原理
(1) ios裝置的記憶體有限,如果用uitableview顯示成千上萬條資料,就需要成千上萬 個uitableviewcell物件的話,那將會耗盡ios裝置的記憶體。要解決該問題,需要重用uitableviewcell物件
(2)重⽤原理
:當滾動列表時,部分
uitableviewcell
會移出視窗,
uitableview
會將視窗外的
uitableviewcell
放入乙個物件池中,等待重用。當
uitableview
要求datasource
返回 uitableviewcell
時,datasource
會先檢視這個物件池,如果池中有未使用的
uitableviewcell
,datasource則
會用新的資料來配置這個
uitableviewcell
,然後返回給
uitableview
,重新顯示到視窗中,從而避免建立新物件 。這樣可以讓建立的cell的數量維持在很低的水平,如果乙個視窗中只能顯示5個cell,那麼cell重用之後,只需要建立6個cell就夠了。
(3)注意點:還有⼀個非常重要的問題:有時候需要自定義uitableviewcell(用⼀個子類繼 承uitableviewcell),而且每⼀行⽤的不一定是同一種uitableviewcell,所以一 個uitableview可能擁有不同型別的uitableviewcell,物件池中也會有很多不同型別的 uitableviewcell,那麼uitableview在重⽤用uitableviewcell時可能會得到錯誤型別的 uitableviewcell
解決⽅方案
:uitableviewcell
有個nsstring *
reuseidentifier
屬性,可以在初始化
uitableviewcell
的時候傳入乙個特定的字串標識來設定
reuseidentifier(
一般用uitableviewcell
的類名)
。當uitableview
要求datasource
返回uitableviewcell
時,先 通過乙個字串標識到物件池中查詢對應型別的
uitableviewcell
物件,如果有,就重用,如果沒有,就傳入這個字串標識來初始化⼀乙個
uitableviewcell
物件。
示例:
說明:乙個視窗放得下(可視)三個cell,整個程式只需要建立4個該型別的cell即可。
四、cell的優化**
**示例:
1快取優化的思路:#import
"njviewcontroller.h"2
#import
"njhero.h"3
4//#define id @"abc"56
@inte***ce njviewcontroller ()7/**
8* 儲存所有的英雄資料9*/
10 @property (nonatomic, strong) nsarray *heros;
11 @property (weak, nonatomic) iboutlet uitableview *tableview;
1213
@end
1415
@implementation
njviewcontroller
1617
#pragma mark - 懶載入
18 - (nsarray *)heros
1931
//4.賦值資料
32 _heros =[models copy];33}
34//
4.返回資料
35return
_heros;36}
3738 - (void
)viewdidload
3945
46#pragma mark - uitableviewdatasource
47//
返回多少組
48 - (nsinteger)numberofsectionsintableview:(uitableview *)tableview
4952
//返回每一組有多少行
53 - (nsinteger) tableview:(uitableview *)tableview numberofrowsinsection:(nsinteger)section
5457
//當乙個cell出現視野範圍內的時候就會呼叫
58//
返回哪一組的哪一行顯示什麼內容
59 - (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath
6072
//4.給cell設定資料
73 njhero *hero =self.heros[indexpath.row];
74 cell.textlabel.text =hero.name;
75 cell.detailtextlabel.text =hero.intro;
76 cell.imageview.image =[uiimage imagenamed:hero.icon];
7778
//nslog(@"%@ - %d - %p", hero.name, indexpath.row, cell);
7980
//3.返回cell
81return
cell;82}
8384
#pragma mark - 控制狀態列是否顯示
85/**86
* 返回yes代表隱藏狀態列, no相反
87*/
88 -(bool)prefersstatusbarhidden
8992
@end
(1)先去快取池中查詢是否有滿足條件的cell,若有那就直接拿來
(2)若沒有,就自己建立乙個cell
(3)建立cell,並且設定乙個唯一的標記(把屬於「」的給蓋個章)
(4)給cell設定資料
注意點:
定義變數用來儲存重用標記的值,這裡不推薦使用巨集(#define來處理),因為該變數只在這個作用域的內部使用,且如果使用巨集定義的話,定義和使用位置太分散,不利於閱讀程式。由於其值不變,沒有必要每次都開
cell重用機制
i ios 裝置的記憶體有限,如果用 uitableview 顯示成千上萬條資料,就需要成千上萬個 uitableviewcell 物件的話,那將會耗盡 ios裝置的記憶體。要解決該問題,需要重用 uitableviewcell物件 n重用原理 當滾動列表時,部分 uitableviewcell 會...
cell重用機制
對於程式而言,記憶體控制是必不可少的。如果乙個tableview中有1000個cell,乙個個建立的話會消耗很大的記憶體,很容易出現記憶體報警,cell的重用機制就是為了節省記憶體的一種機制。只建立螢幕能顯示的最大個數的cell,然後重複使用這些cell,對cell進行單獨的顯示分配,這樣既不影響顯...
iOS tableView可重用cell的兩個方法
dequeuereusablecellwithidentifier dequeuereusablecellwithidentifier forindexpath 這兩個方法的區別總結下。storyboard自定義cell 如果使用 storyboard 並且,在 storyboard 中指定了 單元...