iOS

YYWebImage源码分析

2018-03-08  本文已影响5人  踏云小子

1. 网络请求下载图片

YY用的是NSURLConnection,这个其实可以用NSURLSession替换

2. 图片解码

2.1 判断图片格式

2.2 不同图片格式对应不同的显示方式

2.3 如何判断图片格式

取图片数据的第一个字节

//通过图片Data数据第一个字节 来获取图片扩展名
- (NSString *)contentTypeForImageData:(NSData *)data{
    uint8_t c;
    [data getBytes:&c length:1];
    switch (c) {
        case 0xFF:
            return @"jpeg";
        case 0x89:
            return @"png";
        case 0x47:
            return @"gif";
        case 0x49:
        case 0x4D:
            return @"tiff";
        case 0x52:
            if ([data length] < 12) {
                return nil;
            }
            NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
            if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
                return @"webp";
            }
            return nil;
    }
    return nil;
}

2.4 图片缓存设置

NSURLRequest 有个 cachePolicy 属性,它根据以下常量指定了请求的缓存行为:

如果你需要更精确的缓存策略,NSURLSessionDataDelegate代理里的URLSession:dataTask:willCacheResponse:completionHandler:方法或者NSURLConnection的connection:willCacheResponse:可以实现

2.5 为什么用pthread_mutex_lock对图片原始处理时加锁,怎么使用?

之所以用pthread_mutex_lock是因为dispacth_semaphore无法解决递归调用问题,同时性能上NSRecursiveLock也没有它好,而处理图片二进制数据对性能有一定要求,所以用pthread_mutex_lock
YYWebImage的源码如下

- (instancetype)initWithScale:(CGFloat)scale {
    self = [super init];
    if (scale <= 0) scale = 1;
    _scale = scale;
    _framesLock = dispatch_semaphore_create(1);
    
    pthread_mutexattr_t attr;
    pthread_mutexattr_init (&attr);
    pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);//设置锁为递归锁
    pthread_mutex_init (&_lock, &attr);
    pthread_mutexattr_destroy (&attr);
    
    return self;
}
- (BOOL)updateData:(NSData *)data final:(BOOL)final {
    BOOL result = NO;
    pthread_mutex_lock(&_lock);
    result = [self _updateData:data final:final];
    pthread_mutex_unlock(&_lock);
    return result;
}

关于pthread_mutex_lock 的使用详见这里

2.6 PNG图片的解码

对于png,作者是拿到全部数据后再渲染,我之前做过一个边拿数据边渲染的测试,结果很耗资源;而jpeg图片,则是边拿到数据边渲染

上一篇下一篇

猜你喜欢

热点阅读