-
-
Notifications
You must be signed in to change notification settings - Fork 68
/
Copy pathMLRNImageQueueOperation.m
134 lines (117 loc) · 4.28 KB
/
MLRNImageQueueOperation.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#import "MLRNImageQueueOperation.h"
typedef NS_ENUM(NSInteger, MLRNImageQueueOperationState) {
IOState_Initial,
IOState_CancelledDoNotExecute,
IOState_Executing, // cancellationBlock is set
IOState_Finished,
/* Not sates, just selectors for only and except params */
IOState_Filter_None,
IOState_Filter_All,
};
@interface MLRNImageQueueOperation ()
@property (nonatomic) MLRNImageQueueOperationState state;
@end
@implementation MLRNImageQueueOperation {
RCTImageLoaderCancellationBlock _cancellationBlock;
BOOL _cancelled;
}
- (instancetype)init {
self = [super init];
if (self) {
_state = IOState_Initial;
_cancelled = false;
}
return self;
}
- (BOOL)isExecuting {
@synchronized(self) {
return self.state == IOState_Executing;
}
}
- (BOOL)isFinished {
@synchronized(self) {
return (self.state == IOState_Finished || self.state == IOState_CancelledDoNotExecute);
}
}
- (BOOL)isCancelled {
@synchronized(self) {
return self.state == IOState_CancelledDoNotExecute;
}
}
- (void)setCancellationBlock:(dispatch_block_t)block {
_cancellationBlock = block;
}
- (void)callCancellationBlock {
if (_cancellationBlock) {
_cancellationBlock();
}
}
- (MLRNImageQueueOperationState)setState:(MLRNImageQueueOperationState)newState
only:(MLRNImageQueueOperationState)only
except:(MLRNImageQueueOperationState)except {
MLRNImageQueueOperationState prevState = IOState_Filter_None;
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isCancelled"];
@synchronized(self) {
BOOL allowed = YES;
prevState = self.state;
if (!(only == IOState_Filter_All || prevState == only)) {
allowed = NO;
}
if (prevState == except) {
allowed = NO;
}
if (allowed) {
self.state = newState;
}
}
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
[self didChangeValueForKey:@"isCancelled"];
return prevState;
}
- (MLRNImageQueueOperationState)setState:(MLRNImageQueueOperationState)newState
only:(MLRNImageQueueOperationState)only {
return [self setState:newState only:only except:IOState_Filter_None];
}
- (MLRNImageQueueOperationState)setState:(MLRNImageQueueOperationState)newState
except:(MLRNImageQueueOperationState)except {
return [self setState:newState only:IOState_Filter_All except:except];
}
- (void)start {
if (self.state == IOState_CancelledDoNotExecute) {
return;
}
__weak MLRNImageQueueOperation *weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf
setCancellationBlock:[[weakSelf.bridge moduleForName:@"ImageLoader"
lazilyLoadIfNecessary:YES]
loadImageWithURLRequest:weakSelf.urlRequest
size:CGSizeZero
scale:weakSelf.scale
clipped:YES
resizeMode:RCTResizeModeStretch
progressBlock:nil
partialLoadBlock:nil
completionBlock:^void(NSError *error, UIImage *image) {
if (image && weakSelf.sdf) {
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
}
weakSelf.completionHandler(error, image);
[weakSelf setState:IOState_Finished
except:IOState_Finished];
}]];
if ([weakSelf setState:IOState_Executing
only:IOState_Initial] == IOState_CancelledDoNotExecute) {
[weakSelf callCancellationBlock];
}
});
}
- (void)cancel {
if ([self setState:IOState_CancelledDoNotExecute except:IOState_Finished] == IOState_Executing) {
[self callCancellationBlock];
}
}
@end