diff --git a/ios/sdk/component/image/HippyImageView.m b/ios/sdk/component/image/HippyImageView.m index f189fa475..eab63c171 100644 --- a/ios/sdk/component/image/HippyImageView.m +++ b/ios/sdk/component/image/HippyImageView.m @@ -131,6 +131,7 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius) @interface HippyImageView () { NSURLSessionDataTask *_task; + NSURL *_imageLoadURL; long long _totalLength; NSMutableData *_data; __weak CALayer *_borderWidthLayer; @@ -267,10 +268,10 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius) - (void)reloadImage { NSDictionary *source = [self.source firstObject]; - if (source && CGRectGetWidth(self.frame) > 0 && CGRectGetHeight(self.frame) > 0) { - if (_onLoadStart) { - _onLoadStart(@{}); - } + if (source && CGRectGetWidth(self.frame) > 0 && CGRectGetHeight(self.frame) > 0) { + if (_onLoadStart) { + _onLoadStart(@{}); + } NSString *uri = source[@"uri"]; BOOL isBlurredImage = NO; @@ -291,7 +292,7 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius) BOOL fileExist = [[NSFileManager defaultManager] fileExistsAtPath:localPath isDirectory:&isDirectory]; if (fileExist && !isDirectory) { NSData *imageData = [NSData dataWithContentsOfFile:localPath]; - Class ipClass = imageProviderClassFromBridge(imageData, _bridge); + Class ipClass = imageProviderClassFromBridge(imageData, self.bridge); id instance = [self instanceImageProviderFromClass:ipClass imageData:imageData]; BOOL isAnimatedImage = [ipClass isAnimatedImage:imageData]; if (isAnimatedImage) { @@ -312,19 +313,45 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius) } return; } - if(_bridge.imageLoader && source_url) { - if (_defaultImage) { - self.image = _defaultImage; + + __weak typeof(self) weakSelf = self; + + typedef void (^HandleBase64CompletedBlock)(NSString *); + HandleBase64CompletedBlock handleBase64CompletedBlock = ^void(NSString *base64Data) { + NSRange range = [base64Data rangeOfString:@";base64,"]; + if (NSNotFound != range.location) { + base64Data = [base64Data substringFromIndex:range.location + range.length]; + NSData *imageData = [[NSData alloc] initWithBase64EncodedString:base64Data + options: NSDataBase64DecodingIgnoreUnknownCharacters]; + Class ipClass = imageProviderClassFromBridge(imageData, self.bridge); + id instance = [self instanceImageProviderFromClass:ipClass imageData:imageData]; + BOOL isAnimatedImage = [ipClass isAnimatedImage:imageData]; + if (isAnimatedImage) { + if (weakSelf.animatedImageOperation) { + [weakSelf.animatedImageOperation cancel]; + } + weakSelf.animatedImageOperation = [[HippyAnimatedImageOperation alloc] initWithAnimatedImageProvider:instance imageView:self imageURL:source[@"uri"]]; + [animated_image_queue() addOperation:weakSelf.animatedImageOperation]; + } + else { + UIImage *image = [instance image]; + NSError *error = nil; + if (!image) { + error = [NSError errorWithDomain: NSURLErrorDomain code: -1 userInfo: @{NSLocalizedDescriptionKey: @"base64 url is invalidated"}]; + } + [weakSelf loadImage: image url: source[@"uri"] error: error needBlur:YES needCache:YES]; + } } - __weak __typeof(self) weakSelf = self; - [_bridge.imageLoader imageView:weakSelf loadAtUrl:source_url placeholderImage:_defaultImage context: NULL progress:^(long long currentLength, long long totalLength) { - __typeof(weakSelf) strongSelf = weakSelf; - if (strongSelf.onProgress) { - strongSelf.onProgress(@{@"loaded": @((double)currentLength), @"total": @((double)totalLength)}); - } - } completed:^(NSData *data, NSURL *url, NSError *error) { - __typeof(weakSelf) strongSelf = weakSelf; - Class ipClass = imageProviderClassFromBridge(data, strongSelf.bridge); + }; + + typedef void(^HandleImageCompletedBlock)(NSURL *); + HandleImageCompletedBlock handleImageCompletedBlock = ^void(NSURL *source_url) { + [weakSelf.bridge.imageLoader imageView:weakSelf loadAtUrl:source_url placeholderImage:weakSelf.defaultImage context: NULL progress:^(long long currentLength, long long totalLength) { + if (weakSelf.onProgress) { + weakSelf.onProgress(@{@"loaded": @((double)currentLength), @"total": @((double)totalLength)}); + } + } completed:^(NSData *data, NSURL *url, NSError *error) { + Class ipClass = imageProviderClassFromBridge(data, self.bridge); id instance = [self instanceImageProviderFromClass:ipClass imageData:data]; BOOL isAnimatedImage = [ipClass isAnimatedImage:data]; if (isAnimatedImage) { @@ -334,38 +361,36 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius) weakSelf.animatedImageOperation = [[HippyAnimatedImageOperation alloc] initWithAnimatedImageProvider:instance imageView:self imageURL:source[@"uri"]]; [animated_image_queue() addOperation:weakSelf.animatedImageOperation]; } - else { - UIImage *image = [instance image]; - [weakSelf loadImage: image url: url.absoluteString error: error needBlur:YES needCache:YES]; - } - }]; - } else { - if ([uri hasPrefix: @"data:image/"]) { - NSString *base64Data = uri; - NSRange range = [uri rangeOfString:@";base64,"]; - if (NSNotFound != range.location) { - base64Data = [uri substringFromIndex:range.location + range.length]; - } - NSData *imageData = [[NSData alloc] initWithBase64EncodedString:base64Data options: NSDataBase64DecodingIgnoreUnknownCharacters]; - Class ipClass = imageProviderClassFromBridge(imageData, self.bridge); - id instance = [self instanceImageProviderFromClass:ipClass imageData:imageData]; - BOOL isAnimatedImage = [ipClass isAnimatedImage:imageData]; - if (isAnimatedImage) { - if (_animatedImageOperation) { - [_animatedImageOperation cancel]; - } - _animatedImageOperation = [[HippyAnimatedImageOperation alloc] initWithAnimatedImageProvider:instance imageView:self imageURL:source[@"uri"]]; - [animated_image_queue() addOperation:_animatedImageOperation]; - } else { UIImage *image = [instance image]; NSError *error = nil; if (!image) { error = [NSError errorWithDomain: NSURLErrorDomain code: -1 userInfo: @{NSLocalizedDescriptionKey: @"base64 url is invalidated"}]; } - [self loadImage: image url: source[@"uri"] error: error needBlur:YES needCache:YES]; + [weakSelf loadImage: image url: source[@"uri"] error: error needBlur:YES needCache:YES]; } - } + }]; + }; + + if(_bridge.imageLoader && source_url) { + if (_defaultImage) { + weakSelf.image = _defaultImage; + } + + if ([[source_url absoluteString] hasPrefix: @"data:image/"]) { + handleBase64CompletedBlock([source_url absoluteString]); + } else { + if (_imageLoadURL) { + [_bridge.imageLoader cancelImageDownload:self withUrl:_imageLoadURL]; + } + _imageLoadURL = source_url; + handleImageCompletedBlock(source_url); + } + + } else { + if ([uri hasPrefix: @"data:image/"]) { + handleBase64CompletedBlock(uri); + } else { if (_task) { [self cancelImageLoad]; @@ -375,8 +400,8 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius) _task = [session dataTaskWithURL:source_url]; [_task resume]; } - } - } + } + } } - (void)cancelImageLoad @@ -558,7 +583,7 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius) // self.layer.magnificationFilter = kCAFilterTrilinear; if (image.images) { - HippyAssert(NO, @"GIF图片不应该进入这个逻辑"); + HippyAssert(NO, @"GIF should not invoke this"); } else { self.image = image;