隨着市場上愈來愈多的APP上線,好多軟件對手機的內存要求也是很大,因此咱們在開發的時候必定要掌握如何去優化內存,將本身的APP儘量優化。今天咱們就一塊兒看一下九宮格的優化。下面是軟件的截圖java
一、爲了達到更好的效果咱們不用UITableView,首先咱們要經過XIB自定義一個圖片和文字如圖:數組
二、自定義主視圖JRMainScrollView,經過協議代理來實現功能,作法和UITableView相似,你們能夠參考一下UITableViewdom
首先:咱們要定義數據源協議ide
<span style="font-family:Arial;font-size:14px;">//數據源協議 @protocol JRMainScrollDataSource <NSObject> //獲取總的數量 - (NSInteger) numberOfItems; //獲取列的數量 - (NSInteger) numberOfColumsOfRow; //獲取item - (UIView *) mainScrollView:(JRMainScrollView *)mainScrollView itemAtIndex:(NSInteger) index; @end</span>
其次:咱們要定義屬性協議佈局
<span style="font-family:Arial;font-size:14px;">//屬性協議 @protocol JRMainScrollDelegate <NSObject> @optional //獲取高度 - (CGFloat) heightForItemAtView:(JRMainScrollView *) mainScrollView; //獲取寬度 - (CGFloat) widthForItemAtView:(JRMainScrollView *) mainScrollView; //獲取間距 - (CGFloat) mainScrollView:(JRMainScrollView *)mainScrollView spaceForItemWithType:(kJRMainScrollItemSpace)type; @end</span>
注意獲取間距包括到左右的間距和上下的間距經過定義一個枚舉實現優化
<span style="font-family:Arial;font-size:14px;">typedef enum{ kJRMainScrollItemLeftSpace, kJRMainScrollItemTopSpace } kJRMainScrollItemSpace;</span>
三、內部佈局實現,計算出當前全部的frame,而且放入數組在此期間,用的的屬性參數都須要從代理來獲取,代碼以下atom
<span style="font-family:Arial;font-size:14px;">//加載子視圖 - (void)_loadSubViews{ //獲取總個數和列數 NSInteger totalItems=[self.jrDataSource numberOfItems]; NSInteger colum=[self.jrDataSource numberOfColumsOfRow]; //獲取寬度和高度 CGFloat itemWidth=[self.jrDelegate widthForItemAtView:self]; CGFloat itemHeigt=[self.jrDelegate heightForItemAtView:self]; //獲取上下間距 CGFloat leftSpace=[self.jrDelegate mainScrollView:self spaceForItemWithType:kJRMainScrollItemLeftSpace]; CGFloat topSpace=[self.jrDelegate mainScrollView:self spaceForItemWithType:kJRMainScrollItemTopSpace]; CGFloat space=(kWidth-2*leftSpace-colum*itemWidth)/(colum-1)+itemWidth; for (int i=0;i<totalItems;i++) { int clo=i%colum; int row=i/colum; CGRect frame=CGRectMake(leftSpace+clo*space, 20+row*(itemHeigt+topSpace), itemWidth, itemHeigt); [self.array addObject:[NSValue valueWithCGRect:frame]]; } self.contentSize=CGSizeMake(0, CGRectGetMaxY([[self.array lastObject] CGRectValue])); self.showsVerticalScrollIndicator=NO; }</span>
四、判斷當前的frame是否是在當前的屏幕可視範圍以內,若是要是在的進行視圖的渲染,若是不在不予理睬。加密
<span style="font-family:Arial;font-size:14px;">-(void)layoutSubviews{ [super layoutSubviews]; //循環便利獲取在屏幕中的frame for (int i=0;i<self.array.count;i++) { UIView * tempView=(UIView *)self.current[@(i)]; CGRect rect=[self.array[i] CGRectValue]; if ([self isInScreenWith:rect]) { if(!tempView){//字典裏沒有的才須要重從新加載 UIView *view=[self.jrDataSource mainScrollView:self itemAtIndex:i]; view.frame=rect; [self.current setObject:view forKey:@(i)]; [self addSubview:view]; } }else if(tempView){//若是存在字典並且不在視線內部的則移除 [self.current removeObjectForKey:@(i)]; [tempView removeFromSuperview]; [self.pool addObject:tempView]; } } //判斷是否是在視野內部,其中有兩種狀況,Y值在屏幕內部,或者MAXY值在屏幕內部 - (BOOL) isInScreenWith:(CGRect) frame{ CGFloat setMiny=self.contentOffset.y; CGFloat setMaxy=self.contentOffset.y+kHeight; BOOL condition1=frame.origin.y>=setMiny&&frame.origin.y<=setMaxy; BOOL condition2=CGRectGetMaxY(frame)>=setMiny&&CGRectGetMaxY(frame)<=setMaxy; if(condition1||condition2){ return YES; } return NO; }</span>
五、操做緩衝池重複利用對象spa
<span style="font-family:Arial;font-size:14px;">/** 存放frame*/ @property(nonatomic,strong) NSMutableArray * array; /** 存放當前顯示的對象*/ @property(nonatomic,strong) NSMutableDictionary * current; /** 存放緩衝池對象*/ @property(nonatomic,strong) NSMutableSet * pool; /** * 獲取重複利用的對象 * * @param identy <#identy description#> * * @return <#return value description#> */ - (JRRectView *) dequeueReusedItemWithIdenty:(NSString *) identy{ JRRectView * view=[self.pool anyObject]; if (view!=nil) { [self.pool removeObject:view]; } return view; }</span>
六、在主控制器加載視圖並實現代理方法便可代理
<span style="font-family:Arial;font-size:14px;"> //加載全部數據 - (void) _loadSubviews{ //1 增長滾動視圖 JRMainScrollView * mainScroll=[[JRMainScrollView alloc] initWithFrame:self.view.bounds]; mainScroll.jrDataSource=self; mainScroll.jrDelegate=self; [mainScroll reloadViews]; [self.view addSubview:mainScroll]; } #pragma mark - 數據源方法 -(NSInteger)numberOfItems{ return 132; } -(NSInteger) numberOfColumsOfRow{ return 3; } -(UIView *) mainScrollView:(JRMainScrollView *)mainScrollView itemAtIndex:(NSInteger)index{ JRRectView *cell=[mainScrollView dequeueReusedItemWithIdenty:@"test"]; if (cell==nil) { cell=[[[NSBundle mainBundle] loadNibNamed:@"rect" owner:nil options:nil] lastObject]; } cell.titleLabel.text=[NSString stringWithFormat:@"下載"]; NSString * imageName=[NSString stringWithFormat:@"%d",arc4random_uniform(20)+256]; UIImage *image=[UIImage imageNamed:imageName]; cell.image.image=image; return cell; } #pragma mark - 代理方法 //獲取高度 - (CGFloat) heightForItemAtView:(JRMainScrollView *) mainScrollView{ return 100; } //獲取寬度 - (CGFloat) widthForItemAtView:(JRMainScrollView *) mainScrollView{ return 90; } //獲取間距 - (CGFloat) mainScrollView:(JRMainScrollView *)mainScrollView spaceForItemWithType:(kJRMainScrollItemSpace)type{ if (type==kJRMainScrollItemLeftSpace) { return 20; }else if (type==kJRMainScrollItemTopSpace){ return 20; } return 20; }</span>
七、內存優化,除了上面6點,還要懂得源碼的優化,一鍵清除Log(開發日誌)信息,一鍵優化減小加密後原包大小