Contents
  1. 1. Store
  2. 2. Retrieval
  3. 3. How UIImage is created
  4. 4. Use another SDImageCache

Store

SDWebImage stores UIImage in memCache first, then into disk. UIImage gets compressed to NSData before going to disk
In SDImageCache.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk {
if (!image || !key) {
return;
}

[self.memCache setObject:image forKey:key cost:image.size.height * image.size.width * image.scale * image.scale];

if (toDisk) {
// ...

if (imageIsPng) {
data = UIImagePNGRepresentation(image);
}
else {
data = UIImageJPEGRepresentation(image, (CGFloat)1.0);
}
#else
data = [NSBitmapImageRep representationOfImageRepsInArray:image.representations usingType: NSJPEGFileType properties:nil];
#endif
}

if (data) {
if (![_fileManager fileExistsAtPath:_diskCachePath]) {
[_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
}

[_fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil];
}
}

Note that NSFileManager createFileAtPath:contents:data:attributes:nil: returns NO if the write operation fails. This includes not enough disk space. See detect no disk space iPhone SDK

Retrieval

SDWebImage will first check to see if the images are in local before going to make network request
In SDImageCache.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
- (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock {
if (!doneBlock) {
return nil;
}

if (!key) {
doneBlock(nil, SDImageCacheTypeNone);
return nil;
}

// First check the in-memory cache...
UIImage *image = [self imageFromMemoryCacheForKey:key];
if (image) {
doneBlock(image, SDImageCacheTypeMemory);
return nil;
}

NSOperation *operation = [NSOperation new];
dispatch_async(self.ioQueue, ^{
if (operation.isCancelled) {
return;
}

@autoreleasepool {
UIImage *diskImage = [self diskImageForKey:key];
if (diskImage) {
CGFloat cost = diskImage.size.height * diskImage.size.width * diskImage.scale * diskImage.scale;
[self.memCache setObject:diskImage forKey:key cost:cost];
}

dispatch_async(dispatch_get_main_queue(), ^{
doneBlock(diskImage, SDImageCacheTypeDisk);
});
}
});

return operation;
}

How UIImage is created

SDWebImage uses SDWebImageDownloaderOperation and NSURLConnection to kick off network requests.
UIImage is created by a call to sd_imageWithData:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
+ (UIImage *)sd_imageWithData:(NSData *)data {
UIImage *image;
NSString *imageContentType = [NSData sd_contentTypeForImageData:data];
if ([imageContentType isEqualToString:@"image/gif"]) {
image = [UIImage sd_animatedGIFWithData:data];
}
#ifdef SD_WEBP
else if ([imageContentType isEqualToString:@"image/webp"])
{
image = [UIImage sd_imageWithWebPData:data];
}
#endif
else {
image = [[UIImage alloc] initWithData:data];
UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
if (orientation != UIImageOrientationUp) {
image = [UIImage imageWithCGImage:image.CGImage
scale:image.scale
orientation:orientation];
}
}


return image;
}

Use another SDImageCache

From SDWebImage,


It is also possible to use the async based image cache store independently. SDImageCache maintains a memory cache and an optional disk cache. Disk cache write operations are performed asynchronous so it doesn’t add unnecessary latency to the UI.
The SDImageCache class provides a singleton instance for convenience but you can create your own instance if you want to create separated cache namespace
Contents
  1. 1. Store
  2. 2. Retrieval
  3. 3. How UIImage is created
  4. 4. Use another SDImageCache