Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit 03fb703

Browse files
maickigarrettmoon
authored andcommitted
Add support for setting a static image to ASNetworkImageNode
1 parent 9c094ff commit 03fb703

2 files changed

Lines changed: 60 additions & 18 deletions

File tree

AsyncDisplayKit/ASNetworkImageNode.mm

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ @interface ASNetworkImageNode ()
4343
id _downloadIdentifierForProgressBlock;
4444

4545
BOOL _imageLoaded;
46+
BOOL _imageWasSetExternally;
4647
CGFloat _currentImageQuality;
4748
CGFloat _renderedImageQuality;
4849
BOOL _shouldRenderProgressImages;
@@ -120,7 +121,25 @@ - (void)dealloc
120121

121122
- (void)setImage:(UIImage *)image
122123
{
123-
ASDisplayNodeAssert(NO, @"Setting the image directly to an ASNetworkImageNode is not allowed. Please either use the defaultImage property or move to an ASImageNode");
124+
__instanceLock__.lock();
125+
_imageWasSetExternally = (image != nil);
126+
if (_imageWasSetExternally) {
127+
[self __cancelDownloadAndClearImage];
128+
}
129+
__instanceLock__.unlock();
130+
131+
[self __setImage:image];
132+
}
133+
134+
- (void)_setImage:(UIImage *)image
135+
{
136+
__instanceLock__.lock();
137+
if (_imageWasSetExternally) {
138+
__instanceLock__.unlock();
139+
return;
140+
}
141+
__instanceLock__.unlock();
142+
124143
[self __setImage:image];
125144
}
126145

@@ -133,7 +152,13 @@ - (void)setURL:(NSURL *)URL resetToDefault:(BOOL)reset
133152
{
134153
ASDN::MutexLocker l(__instanceLock__);
135154

136-
if (ASObjectIsEqual(URL, _URL)) {
155+
#ifdef DEBUG
156+
if (_imageWasSetExternally) {
157+
NSLog(@"Image was already set via the .image property. Setting an image explicitly and setting an URL is not supported.");
158+
}
159+
#endif
160+
161+
if (ASObjectIsEqual(URL, _URL) || _imageWasSetExternally) {
137162
return;
138163
}
139164

@@ -144,7 +169,7 @@ - (void)setURL:(NSURL *)URL resetToDefault:(BOOL)reset
144169

145170
BOOL hasURL = _URL == nil;
146171
if (reset || hasURL) {
147-
[self __setImage:_defaultImage];
172+
[self _setImage:_defaultImage];
148173
/* We want to maintain the order that currentImageQuality is set regardless of the calling thread,
149174
so always use a dispatch_async to ensure that we queue the operations in the correct order.
150175
(see comment in displayDidFinish) */
@@ -179,7 +204,7 @@ - (void)setDefaultImage:(UIImage *)defaultImage
179204
dispatch_async(dispatch_get_main_queue(), ^{
180205
self.currentImageQuality = hasURL ? 0.0 : 1.0;
181206
});
182-
[self __setImage:defaultImage];
207+
[self _setImage:defaultImage];
183208
}
184209
}
185210

@@ -264,7 +289,7 @@ - (void)displayWillStartAsynchronously:(BOOL)asynchronously
264289
if (_imageLoaded == NO && _URL && _downloadIdentifier == nil) {
265290
UIImage *result = [[_cache synchronouslyFetchedCachedImageWithURL:_URL] asdk_image];
266291
if (result) {
267-
[self __setImage:result];
292+
[self _setImage:result];
268293
_imageLoaded = YES;
269294
dispatch_async(dispatch_get_main_queue(), ^{
270295
_currentImageQuality = 1.0;
@@ -320,12 +345,12 @@ - (void)didExitPreloadState
320345

321346
{
322347
ASDN::MutexLocker l(__instanceLock__);
323-
324-
[self _cancelImageDownload];
325-
[self _clearImage];
326-
if (_cacheFlags.cacheSupportsClearing) {
327-
[_cache clearFetchedImageFromCacheWithURL:_URL];
348+
// If the image was set explicitly we don't want to remove it while exiting the preload state
349+
if (_imageWasSetExternally) {
350+
return;
328351
}
352+
353+
[self __cancelDownloadAndClearImage];
329354
}
330355
}
331356

@@ -335,7 +360,10 @@ - (void)didEnterPreloadState
335360

336361
{
337362
ASDN::MutexLocker l(__instanceLock__);
338-
[self _lazilyLoadImageIfNecessary];
363+
// Image was set externally no need to load an image
364+
if (_imageWasSetExternally == NO) {
365+
[self _lazilyLoadImageIfNecessary];
366+
}
339367
}
340368
}
341369

@@ -348,7 +376,7 @@ - (void)handleProgressImage:(UIImage *)progressImage progress:(CGFloat)progress
348376
if (ASObjectIsEqual(_downloadIdentifier, downloadIdentifier) == NO && downloadIdentifier != nil) {
349377
return;
350378
}
351-
[self __setImage:progressImage];
379+
[self _setImage:progressImage];
352380
dispatch_async(dispatch_get_main_queue(), ^{
353381
// See comment in -displayDidFinish for why this must be dispatched to main
354382
self.currentImageQuality = progress;
@@ -391,6 +419,15 @@ - (void)_updateProgressImageBlockOnDownloaderIfNeeded
391419
_downloadIdentifierForProgressBlock = newDownloadIDForProgressBlock;
392420
}
393421

422+
- (void)__cancelDownloadAndClearImage
423+
{
424+
[self _cancelImageDownload];
425+
[self _clearImage];
426+
if (_cacheFlags.cacheSupportsClearing) {
427+
[_cache clearFetchedImageFromCacheWithURL:_URL];
428+
}
429+
}
430+
394431
- (void)_clearImage
395432
{
396433
// Destruction of bigger images on the main thread can be expensive
@@ -404,7 +441,7 @@ - (void)_clearImage
404441
ASPerformBackgroundDeallocation(image);
405442
}
406443
self.animatedImage = nil;
407-
[self __setImage:_defaultImage];
444+
[self _setImage:_defaultImage];
408445
_imageLoaded = NO;
409446
// See comment in -displayDidFinish for why this must be dispatched to main
410447
dispatch_async(dispatch_get_main_queue(), ^{
@@ -464,7 +501,7 @@ - (void)_lazilyLoadImageIfNecessary
464501

465502
dispatch_async(dispatch_get_main_queue(), ^{
466503
if (self.shouldCacheImage) {
467-
[self __setImage:[UIImage imageNamed:_URL.path.lastPathComponent]];
504+
[self _setImage:[UIImage imageNamed:_URL.path.lastPathComponent]];
468505
} else {
469506
// First try to load the path directly, for efficiency assuming a developer who
470507
// doesn't want caching is trying to be as minimal as possible.
@@ -494,7 +531,7 @@ - (void)_lazilyLoadImageIfNecessary
494531
if (animatedImage != nil) {
495532
self.animatedImage = animatedImage;
496533
} else {
497-
[self __setImage:nonAnimatedImage];
534+
[self _setImage:nonAnimatedImage];
498535
}
499536
}
500537

@@ -530,7 +567,7 @@ - (void)_lazilyLoadImageIfNecessary
530567
if ([imageContainer asdk_animatedImageData] && _downloaderFlags.downloaderImplementsAnimatedImage) {
531568
strongSelf.animatedImage = [_downloader animatedImageWithData:[imageContainer asdk_animatedImageData]];
532569
} else {
533-
[strongSelf __setImage:[imageContainer asdk_image]];
570+
[strongSelf _setImage:[imageContainer asdk_image]];
534571
}
535572
dispatch_async(dispatch_get_main_queue(), ^{
536573
strongSelf->_currentImageQuality = 1.0;

AsyncDisplayKitTests/ASNetworkImageNodeTests.m

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,15 @@ - (void)testThatProgressBlockIsSetAndClearedCorrectlyOnChangeURL
7171
[downloader verifyWithDelay:5];
7272
}
7373

74-
- (void)testThatSettingAnImageExternallyWillThrow
74+
- (void)testThatSettingAnImageWillStayForEnteringAndExitingPreloadState
7575
{
76+
UIImage *image = [[UIImage alloc] init];
7677
ASNetworkImageNode *networkImageNode = [[ASNetworkImageNode alloc] init];
77-
XCTAssertThrows(networkImageNode.image = [UIImage imageNamed:@""]);
78+
networkImageNode.image = image;
79+
[networkImageNode enterInterfaceState:ASInterfaceStatePreload];
80+
XCTAssertEqualObjects(image, networkImageNode.image);
81+
[networkImageNode exitInterfaceState:ASInterfaceStatePreload];
82+
XCTAssertEqualObjects(image, networkImageNode.image);
7883
}
7984

8085
@end

0 commit comments

Comments
 (0)