美文网首页
iOS 性能优化之界面优化

iOS 性能优化之界面优化

作者: MonKey_Money | 来源:发表于2020-11-29 19:34 被阅读0次

1.卡顿原理

图像撕裂及解决方法图形渲染流程

2.卡顿监测

2.1 YYKit CADisplayLink

YYKit的实质是1/fps = 时间/count fps = count/delta

    _count++;
    NSTimeInterval delta = link.timestamp - _lastTime;
    if (delta < 1) return;
    _lastTime = link.timestamp;
    float fps = _count / delta;
    _count = 0;

如果fps都为60,说明不发生卡顿,如果fps越是小60,说明卡顿越明显

2.2runloop 监测

iOS通过提交事物,事物再唤起runloop进行处理,我们监听runloop的状态可以知道我们提交的事物运行的时间

{
[self registerObserver];
 [self startMonitor];
}
static void CallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
{
    LGBlockMonitor *monitor = (__bridge LGBlockMonitor *)info;
    monitor->activity = activity;
    // 发送信号
    dispatch_semaphore_t semaphore = monitor->_semaphore;
    dispatch_semaphore_signal(semaphore);
}
- (void)registerObserver{
    CFRunLoopObserverContext context = {0,(__bridge void*)self,NULL,NULL};
    //NSIntegerMax : 优先级最小
    CFRunLoopObserverRef observer = CFRunLoopObserverCreate(kCFAllocatorDefault,
                                                            kCFRunLoopAllActivities,
                                                            YES,
                                                            NSIntegerMax,
                                                            &CallBack,
                                                            &context);
    CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes);
}
- (void)startMonitor{
    // 创建信号
    _semaphore = dispatch_semaphore_create(0);
    // 在子线程监控时长
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        while (YES)
        {
            // 超时时间是 1 秒,没有等到信号量,st 就不等于 0, RunLoop 所有的任务
            long st = dispatch_semaphore_wait(self->_semaphore, dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC));
            if (st != 0)
            {
                if (self->activity == kCFRunLoopBeforeSources || self->activity == kCFRunLoopAfterWaiting)
                {
                    if (++self->_timeoutCount < 2){
                        NSLog(@"timeoutCount==%lu",(unsigned long)self->_timeoutCount);
                        continue;
                    }
                    // 一秒左右的衡量尺度 很大可能性连续来 避免大规模打印!
                    NSLog(@"检测到超过两次连续卡顿");
                }
            }
            self->_timeoutCount = 0;
        }
    });
}

2.2.1微信的监测工具
实质也是判断runloop状态间的时候 matrix-wechat

3.实战优化

3.1.预排版+内存缓存

我们在用tableView和UICollectionView显示内容时,有时会出现复杂布局的Cell,为了优化性能,我们可以把布局数据计算好,在加载时直接显示,很好的优化性能增强用户体验。

3.2预解码渲染

我们通过下面代码加载图片

    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1606640873&di=ea6988d5033854f0d3bcebfe4404d890&src=http://a4.att.hudong.com/27/67/01300000921826141299672233506.jpg"]];
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        UIImage *image = [UIImage imageWithData:data];
        dispatch_async(dispatch_get_main_queue(), ^{
            self.myImageView.image = image;
        });
    });
image.png

我们把对图片的解码放到子线程中,对图片的解码可以参看SDWebimage中的SDWebImageDecoder

3.3按需加载

只有在需要显示的地方加载图片,比如我们快速滑动tableView,我们只在停止的位置加载cell,滑动过程的cell不优先加载。

3.4异步渲染

view和layer的关系参照iOS图形渲染流程

ViewAndLayer.png
异步渲染,可以参看美团的Graver

相关文章

网友评论

      本文标题:iOS 性能优化之界面优化

      本文链接:https://www.haomeiwen.com/subject/nvgcwktx.html