Skip to content

Commit 9e17873

Browse files
committed
Using hack to fix the issue that LPLinkView does not work on cell-reusing
1 parent e392621 commit 9e17873

3 files changed

Lines changed: 48 additions & 16 deletions

File tree

Example/SDWebImageLinkPlugin/SDViewController.m

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ @interface LinkTableViewCell : UITableViewCell
1919

2020
@implementation LinkTableViewCell
2121

22-
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier url:(NSURL *)url {
22+
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
2323
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
24-
_linkView = [[LPLinkView alloc] initWithURL:url];
24+
NSURL *url = nil;
25+
_linkView = [[LPLinkView alloc] initWithURL:url]; // We must pass nil here, or will cause Cell-reusing issues on iOS 13.1.
2526
[self.contentView addSubview:_linkView];
2627
}
2728
return self;
@@ -43,7 +44,7 @@ @interface ImageTableViewCell : UITableViewCell
4344

4445
@implementation ImageTableViewCell
4546

46-
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier url:(NSURL *)url {
47+
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
4748
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
4849
_customImageView = [[UIImageView alloc] init];
4950
_customImageView.contentMode = UIViewContentModeScaleAspectFill;
@@ -134,12 +135,12 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
134135

135136
if (self.useLinkView) {
136137
if (![cell isKindOfClass:LinkTableViewCell.class]) {
137-
cell = [[LinkTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier url:url];
138+
cell = [[LinkTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
138139
}
139140
[((LinkTableViewCell *)cell).linkView sd_setImageWithURL:url];
140141
} else {
141142
if (![cell isKindOfClass:ImageTableViewCell.class]) {
142-
cell = [[ImageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier url:url];
143+
cell = [[ImageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
143144
}
144145
((ImageTableViewCell *)cell).customTextLabel.text = url.host;
145146
[((ImageTableViewCell *)cell).customImageView sd_setImageWithURL:url];

SDWebImageLinkPlugin/Classes/LPLinkView+WebCache.m

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
#import "NSURL+SDWebImageLinkPlugin.h"
1111
#import "NSImage+SDWebImageLinkPlugin.h"
1212

13+
#define LPImageClass @"LPImage"
14+
@protocol LPImageProtocol <NSObject>
15+
16+
- (instancetype)initWithPlatformImage:(UIImage *)image;
17+
18+
@end
19+
1320
@implementation LPLinkView (WebCache)
1421

1522
- (void)sd_setImageWithURL:(nullable NSURL *)url {
@@ -62,7 +69,9 @@ - (void)sd_setImageWithURL:(nullable NSURL *)url
6269
metadata = [[LPLinkMetadata alloc] init];
6370
metadata.originalURL = url;
6471
metadata.URL = imageURL;
65-
metadata.imageProvider = [[NSItemProvider alloc] initWithObject:image];
72+
// LPLinkMetadata.imageProvider on iOS 13.1 contains bug which cause async query, and not compatible for cell-reusing. Radar FB7462933
73+
id<LPImageProtocol> linkImage = [[NSClassFromString(LPImageClass) alloc] initWithPlatformImage:image];
74+
[metadata setValue:linkImage forKey:@"image"];
6675
imageURL.sd_linkMetadata = metadata;
6776
} else {
6877
metadata = [[LPLinkMetadata alloc] init];

SDWebImageLinkPlugin/Classes/SDImageLinkLoader.m

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,19 @@
1616
#import <MobileCoreServices/MobileCoreServices.h>
1717
#endif
1818

19-
@interface LPMetadataProvider (SDWebImageOperation) <SDWebImageOperation>
19+
@interface SDImageLinkLoaderOperation : NSObject <SDWebImageOperation>
20+
21+
@property (nonatomic, strong) LPMetadataProvider *provider;
22+
@property (nonatomic, getter=isCancelled) BOOL cancelled;
23+
24+
@end
25+
26+
@implementation SDImageLinkLoaderOperation
27+
28+
- (void)cancel {
29+
[self.provider cancel];
30+
self.cancelled = YES;
31+
}
2032

2133
@end
2234

@@ -61,11 +73,11 @@ - (BOOL)canRequestImageForURL:(NSURL *)url {
6173
}
6274

6375
- (id<SDWebImageOperation>)requestImageWithURL:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock {
76+
SDImageLinkLoaderOperation *operation = [SDImageLinkLoaderOperation new];
6477
// Let's check wether input URL already have an associated LPLinkMetadata
6578
LPLinkMetadata *metadata = url.sd_linkMetadata;
6679
if (metadata) {
67-
[self fetchImageWithMetadata:metadata options:options context:context progress:progressBlock completed:completedBlock];
68-
return nil;
80+
[self fetchImageWithMetadata:metadata operation:operation options:options context:context progress:progressBlock completed:completedBlock];
6981
} else {
7082
LPMetadataProvider *provider = [[LPMetadataProvider alloc] init];
7183
provider.timeout = self.timeout;
@@ -79,13 +91,15 @@ - (BOOL)canRequestImageForURL:(NSURL *)url {
7991
}
8092
// Associated the link metadata to URL, weak reference
8193
url.sd_linkMetadata = metadata;
82-
[self fetchImageWithMetadata:metadata options:options context:context progress:progressBlock completed:completedBlock];
94+
[self fetchImageWithMetadata:metadata operation:operation options:options context:context progress:progressBlock completed:completedBlock];
8395
}];
84-
return provider;
96+
operation.provider = provider;
8597
}
98+
99+
return operation;
86100
}
87101

88-
- (void)fetchImageWithMetadata:(LPLinkMetadata *)metadata options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock {
102+
- (void)fetchImageWithMetadata:(LPLinkMetadata *)metadata operation:(SDImageLinkLoaderOperation *)operation options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock {
89103
NSURL *url = metadata.originalURL;
90104
// Parse context option
91105
BOOL requestData = [context[SDWebImageContextLinkRequestImageData] boolValue];
@@ -108,15 +122,15 @@ - (void)fetchImageWithMetadata:(LPLinkMetadata *)metadata options:(SDWebImageOpt
108122
}
109123
if (requestData) {
110124
// Request the image data and decode
111-
[self fetchImageDataWithProvider:imageProvider url:url options:options context:context progress:progressBlock completed:completedBlock];
125+
[self fetchImageDataWithProvider:imageProvider operation:operation url:url options:options context:context progress:progressBlock completed:completedBlock];
112126
} else {
113127
// Only request the image object, faster
114-
[self fetchImageWithProvider:imageProvider url:url progress:progressBlock completed:completedBlock];
128+
[self fetchImageWithProvider:imageProvider operation:operation url:url progress:progressBlock completed:completedBlock];
115129
}
116130
}
117131

118132
// Fetch image and data with `loadDataRepresentationForTypeIdentifier` API
119-
- (void)fetchImageDataWithProvider:(NSItemProvider *)imageProvider url:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock {
133+
- (void)fetchImageDataWithProvider:(NSItemProvider *)imageProvider operation:(SDImageLinkLoaderOperation *)operation url:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock {
120134
SDImageLinkLoaderContext *loaderContext = [SDImageLinkLoaderContext new];
121135
loaderContext.url = url;
122136
loaderContext.progressBlock = progressBlock;
@@ -125,6 +139,10 @@ - (void)fetchImageDataWithProvider:(NSItemProvider *)imageProvider url:(NSURL *)
125139
if (progressBlock && progress) {
126140
[progress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted)) context:(__bridge void *)(loaderContext)];
127141
}
142+
if (operation.isCancelled) {
143+
// Cancelled
144+
error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:nil];
145+
}
128146
if (error) {
129147
if (completedBlock) {
130148
dispatch_main_async_safe(^{
@@ -151,7 +169,7 @@ - (void)fetchImageDataWithProvider:(NSItemProvider *)imageProvider url:(NSURL *)
151169
}
152170

153171
// Fetch image with `loadObjectOfClass` API
154-
- (void)fetchImageWithProvider:(NSItemProvider *)imageProvider url:(NSURL *)url progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock {
172+
- (void)fetchImageWithProvider:(NSItemProvider *)imageProvider operation:(SDImageLinkLoaderOperation *)operation url:(NSURL *)url progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock {
155173
SDImageLinkLoaderContext *loaderContext = [SDImageLinkLoaderContext new];
156174
loaderContext.url = url;
157175
loaderContext.progressBlock = progressBlock;
@@ -160,6 +178,10 @@ - (void)fetchImageWithProvider:(NSItemProvider *)imageProvider url:(NSURL *)url
160178
if (progressBlock && progress) {
161179
[progress removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted)) context:(__bridge void *)(loaderContext)];
162180
}
181+
if (operation.isCancelled) {
182+
// Cancelled
183+
error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:nil];
184+
}
163185
if (error) {
164186
if (completedBlock) {
165187
dispatch_main_async_safe(^{

0 commit comments

Comments
 (0)