用RunLoop对UICollectionView优化

1,471 阅读1分钟

遇到一个bug, 就是有很多很多图片, 比如5000以上的图片用collectionView去展示的时候, 飞快的滑动会卡死整个界面, 进而卡死整个应用. 我查了一下内存, 47m不多, 不太可能因为内存而卡死. 不知道是什么问题,我估计是collectionview内部对这种数据展示有问题吧 所以优化一下 1, 对runloop进行观察, 并进行事件优化

typedef void(^RunLoopBlock)(void);

-(void)addTask:(RunLoopBlock)block{
    [_showTask addObject:block];
    if (_showTask.count > _taskCount) {
        [_showTask removeObjectAtIndex:0];
    }
}

-(void)addRunLoopObserver{
    CFRunLoopRef runloop = CFRunLoopGetCurrent();
    CFRunLoopObserverContext context = {
        0,
        (__bridge void *)self,
        &CFRetain,
        &CFRelease,
       NULL
    };
    static CFRunLoopObserverRef defaultModeObserver;
    defaultModeObserver = CFRunLoopObserverCreate(NULL, kCFRunLoopBeforeWaiting, YES, 0, &RunLoopCallBack, &context);
    CFRunLoopAddObserver(runloop, defaultModeObserver, kCFRunLoopCommonModes);
    CFRelease(defaultModeObserver);
  
}

static void RunLoopCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info){
    SSChoosePhotoViewController* vc = (__bridge SSChoosePhotoViewController*)info;
    if (vc.showTask.count == 0) {
        return;
    }
    RunLoopBlock task = vc.showTask.firstObject;
    task();
    [vc.showTask removeObjectAtIndex:0];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    SSChoosePhotoCollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([SSChoosePhotoCollectionViewCell class]) forIndexPath:indexPath];
    
   
    JSDateModel* dateModel = self.itemsArray[indexPath.section];

    JSImageModel *model = [dateModel.imageArray objectAtIndex:indexPath.row];
    if ([_uploadArray containsObject:model]) {
        cell.choosed = YES;
    }else{
        cell.choosed = NO;
    }
    if ([model.photoName hasSuffix:@".mp4"]) {
        cell.isVideo = YES;
    }else{
        cell.isVideo = NO;
    }

    __weak typeof(self) weak_self = self;
    [self addTask:^{
        [weak_self showImage:cell model:model];
    }];
    return cell;
}

其实整个逻辑就是自己去针对整个图片加载逻辑优化,主要是用runloop的触发机制去触发UI渲染事件, 一般情况下, UI事件必须在主线程, 实际上底层就是Runloop, 自己控制任务数量(一般我自己设置为20), 这样在滑动的时候就会顺畅很多,而且不会出现卡死的情况