forked from k06a/NSData-AsyncCacher
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNSData+AsyncCacher.m
94 lines (80 loc) · 2.97 KB
/
NSData+AsyncCacher.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//
// NSData+AsyncCacher.m
// Meetweet
//
// Created by Антон Буков on 28.06.13.
// Copyright (c) 2013 Anton Bukov. All rights reserved.
//
#import "NSData+AsyncCacher.h"
#import "./SAMCache/SAMCache/SAMCache.h"
@implementation NSData (AsyncCacher)
+ (void)getDataFromURL:(NSURL *)url
toBlock:(void(^)(NSData * data, BOOL * retry))block
{
return [NSData getDataFromURL:url toBlock:block needCache:YES];
}
+ (void)getDataFromURL:(NSURL *)url
toBlock:(void(^)(NSData * data, BOOL * retry))block
needCache:(BOOL)needCache
{
static SAMCache * cache;
static NSOperationQueue * mainQueue;
static NSOperationQueue * parallelQueue;
static NSMutableDictionary * blocksDict;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
cache = [[SAMCache alloc] initWithName:@"AsyncCacher"];
mainQueue = [[NSOperationQueue alloc] init];
mainQueue.maxConcurrentOperationCount = 1;
parallelQueue = [[NSOperationQueue alloc] init];
parallelQueue.maxConcurrentOperationCount = 64;
blocksDict = [NSMutableDictionary dictionary];
NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4*1024*1024 diskCapacity:20*1024*1024 diskPath:nil];
[NSURLCache setSharedURLCache:URLCache];
});
if (url == nil && block == nil)
return [cache unloadAllObjects];
if (url == nil)
return;
NSData * object = [cache objectForKey:url.absoluteString];
if (needCache && object)
{
BOOL retry = NO;
block(object, &retry);
if (!retry)
return;
}
[mainQueue addOperationWithBlock:^{
NSMutableArray * blocks = blocksDict[url];
if (blocks == nil)
{
blocks = [NSMutableArray array];
blocksDict[url] = blocks;
}
[blocks addObject:((id)block ?: (id)[NSNull null])];
if (blocks.count != 1)
return;
[parallelQueue addOperationWithBlock:^
{
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:url] queue:mainQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
if (data && needCache)
[cache setObject:data forKey:url.absoluteString];
for (id a in blocks)
{
void(^aBlock)(NSData *,BOOL *) = a;
if ((id)aBlock == [NSNull null])
continue;
dispatch_async(dispatch_get_main_queue(), ^{
BOOL retry = NO;
aBlock(data, &retry);
if (retry)
[NSData getDataFromURL:url toBlock:aBlock needCache:needCache];
});
}
[blocks removeAllObjects];
}];
}];
}];
}
@end