Change that the `sd_imageProgress` property to not auto-create instance by framework. Instead, let users to use KVO and trigger the creation, improve the performance and fix potential issue for most of common usage.

This commit is contained in:
DreamPiggy 2019-06-18 19:15:31 +08:00
parent 2bbe973f59
commit 0c34657bc5
2 changed files with 13 additions and 10 deletions

View File

@ -35,7 +35,7 @@ typedef void(^SDSetImageBlock)(UIImage * _Nullable image, NSData * _Nullable ima
* The current image loading progress associated to the view. The unit count is the received size and excepted size of download. * The current image loading progress associated to the view. The unit count is the received size and excepted size of download.
* The `totalUnitCount` and `completedUnitCount` will be reset to 0 after a new image loading start (change from current queue). And they will be set to `SDWebImageProgressUnitCountUnknown` if the progressBlock not been called but the image loading success to mark the progress finished (change from main queue). * The `totalUnitCount` and `completedUnitCount` will be reset to 0 after a new image loading start (change from current queue). And they will be set to `SDWebImageProgressUnitCountUnknown` if the progressBlock not been called but the image loading success to mark the progress finished (change from main queue).
* @note You can use Key-Value Observing on the progress, but you should take care that the change to progress is from a background queue during download(the same as progressBlock). If you want to using KVO and update the UI, make sure to dispatch on the main queue. And it's recommand to use some KVO libs like KVOController because it's more safe and easy to use. * @note You can use Key-Value Observing on the progress, but you should take care that the change to progress is from a background queue during download(the same as progressBlock). If you want to using KVO and update the UI, make sure to dispatch on the main queue. And it's recommand to use some KVO libs like KVOController because it's more safe and easy to use.
* @note The getter will create a progress instance if the value is nil. You can also set a custom progress instance and let it been updated during image loading * @note The getter will create a progress instance if the value is nil. But by default, we don't create one. If you need to use Key-Value Observing, you must trigger the getter or set a custom progresss instance before the loading start. The default value is nil.
* @note Note that because of the limitations of categories this property can get out of sync if you update the progress directly. * @note Note that because of the limitations of categories this property can get out of sync if you update the progress directly.
*/ */
@property (nonatomic, strong, null_resettable) NSProgress *sd_imageProgress; @property (nonatomic, strong, null_resettable) NSProgress *sd_imageProgress;

View File

@ -69,8 +69,9 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
if (url) { if (url) {
// reset the progress // reset the progress
self.sd_imageProgress.totalUnitCount = 0; NSProgress *imageProgress = objc_getAssociatedObject(self, @selector(sd_imageProgress));
self.sd_imageProgress.completedUnitCount = 0; imageProgress.totalUnitCount = 0;
imageProgress.completedUnitCount = 0;
#if SD_UIKIT || SD_MAC #if SD_UIKIT || SD_MAC
// check and start image indicator // check and start image indicator
@ -83,15 +84,16 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
manager = [SDWebImageManager sharedManager]; manager = [SDWebImageManager sharedManager];
} }
@weakify(self);
SDImageLoaderProgressBlock combinedProgressBlock = ^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) { SDImageLoaderProgressBlock combinedProgressBlock = ^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
@strongify(self);
NSProgress *imageProgress = self.sd_imageProgress;
imageProgress.totalUnitCount = expectedSize; imageProgress.totalUnitCount = expectedSize;
imageProgress.completedUnitCount = receivedSize; imageProgress.completedUnitCount = receivedSize;
#if SD_UIKIT || SD_MAC #if SD_UIKIT || SD_MAC
if ([imageIndicator respondsToSelector:@selector(updateIndicatorProgress:)]) { if ([imageIndicator respondsToSelector:@selector(updateIndicatorProgress:)]) {
double progress = imageProgress.fractionCompleted; double progress = 0;
if (expectedSize != 0) {
progress = (double)receivedSize / expectedSize;
}
progress = MAX(MIN(progress, 1), 0); // 0.0 - 1.0
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[imageIndicator updateIndicatorProgress:progress]; [imageIndicator updateIndicatorProgress:progress];
}); });
@ -101,13 +103,14 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
progressBlock(receivedSize, expectedSize, targetURL); progressBlock(receivedSize, expectedSize, targetURL);
} }
}; };
@weakify(self);
id <SDWebImageOperation> operation = [manager loadImageWithURL:url options:options context:context progress:combinedProgressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { id <SDWebImageOperation> operation = [manager loadImageWithURL:url options:options context:context progress:combinedProgressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
@strongify(self); @strongify(self);
if (!self) { return; } if (!self) { return; }
// if the progress not been updated, mark it to complete state // if the progress not been updated, mark it to complete state
if (finished && !error && self.sd_imageProgress.totalUnitCount == 0 && self.sd_imageProgress.completedUnitCount == 0) { if (finished && !error && imageProgress.totalUnitCount == 0 && imageProgress.completedUnitCount == 0) {
self.sd_imageProgress.totalUnitCount = SDWebImageProgressUnitCountUnknown; imageProgress.totalUnitCount = SDWebImageProgressUnitCountUnknown;
self.sd_imageProgress.completedUnitCount = SDWebImageProgressUnitCountUnknown; imageProgress.completedUnitCount = SDWebImageProgressUnitCountUnknown;
} }
#if SD_UIKIT || SD_MAC #if SD_UIKIT || SD_MAC