随着市场上越来越多的APP上线,好多软件对手机的内存要求也是很大,所以我们在开发的时候一定要掌握如何去优化内存,将自己的APP尽可能优化。今天我们就一起看一下九宫格的优化。下面是软件的截图

1、为了达到更好的效果我们不用UITableview,首先大家要通过XIB自定义一个图片和文字如图:

2、自定义主视图JRMainScrollView,通过协议代理来实现功能,做法和UITableView类似,大家可以参考一下UITableView
首先:大家要定义数据源协议
//数据源协议 @protocol JRMainScrollDataSource <NSObject> //获取总的数量 - (NSInteger) numberOfItems; //获取列的数量 - (NSInteger) numberOfColumsOfRow; //获取item - (UIView *) mainScrollView:(JRMainScrollView *)mainScrollView itemAtIndex:(NSInteger) index; @end
其次:大家要定义属性协议
//属性协议 @protocol JRMainScrollDelegate <NSObject> @optional //获取高度 - (CGFloat) heightForItemAtView:(JRMainScrollView *) mainScrollView; //获取宽度 - (CGFloat) widthForItemAtView:(JRMainScrollView *) mainScrollView; //获取间距 - (CGFloat) mainScrollView:(JRMainScrollView *)mainScrollView spaceForItemWithType:(kJRMainScrollItemSpace)type; @end
注意获取间距包括到左右的间距和上下的间距通过定义一个枚举实现
typedef enum{
    kJRMainScrollItemLeftSpace,
    kJRMainScrollItemTopSpace
} kJRMainScrollItemSpace;
3、内部布局实现,计算出当前所有的frame,并且放入数组在此期间,用的的属性参数都需要从代理来获取,代码如下
//加载子视图
- (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;
}
4、判断当前的frame是不是在当前的屏幕可视范围之内,假如要是在的进行视图的渲染,假如不在不予理睬。
-(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;
        }
5、操作缓冲池重复利用对象
/** 存放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;
}
6、在主控制器加载视图并实现代理方法即可
 //加载所有数据
- (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;
}
	
	

