Skip to content

Commit fd40189

Browse files
authored
Merge pull request #48 from SDWebImage/bugfix_animated_image_watchOS
Using the wrapper on watchOS AnimatedImage as well, try to solve the SwiftUI bug of aspectRatio
2 parents 3ae64cf + 28dbd8e commit fd40189

File tree

7 files changed

+271
-42
lines changed

7 files changed

+271
-42
lines changed

SDWebImageSwiftUI.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@
3131
326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
3232
326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
3333
326E480D23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
34+
3276EB00237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
35+
3276EB01237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
36+
3276EB02237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
37+
3276EB03237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
38+
3276EB04237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */; };
39+
3276EB05237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */; };
40+
3276EB06237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */; };
41+
3276EB07237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */; };
3442
32B933E523659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
3543
32B933E623659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
3644
32B933E723659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
@@ -119,6 +127,8 @@
119127
326B8486236335110011BDFB /* ActivityIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicator.swift; sourceTree = "<group>"; };
120128
326B848B236335400011BDFB /* ProgressIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressIndicator.swift; sourceTree = "<group>"; };
121129
326E480923431C0F00C633E9 /* ImageViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewWrapper.swift; sourceTree = "<group>"; };
130+
3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDAnimatedImageInterfaceWrapper.h; sourceTree = "<group>"; };
131+
3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDAnimatedImageInterfaceWrapper.m; sourceTree = "<group>"; };
122132
32B933E423659A1900BB7CAD /* Transition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transition.swift; sourceTree = "<group>"; };
123133
32C43DCC22FD540D00BE87F5 /* SDWebImageSwiftUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSwiftUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
124134
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageManager.swift; sourceTree = "<group>"; };
@@ -177,6 +187,8 @@
177187
children = (
178188
324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */,
179189
324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */,
190+
3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */,
191+
3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */,
180192
);
181193
path = ObjC;
182194
sourceTree = "<group>";
@@ -262,6 +274,7 @@
262274
isa = PBXHeadersBuildPhase;
263275
buildActionMask = 2147483647;
264276
files = (
277+
3276EB00237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
265278
324F61C7235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
266279
32C43DE622FD54CD00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
267280
);
@@ -271,6 +284,7 @@
271284
isa = PBXHeadersBuildPhase;
272285
buildActionMask = 2147483647;
273286
files = (
287+
3276EB01237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
274288
324F61C8235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
275289
32C43E2222FD583A00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
276290
);
@@ -280,6 +294,7 @@
280294
isa = PBXHeadersBuildPhase;
281295
buildActionMask = 2147483647;
282296
files = (
297+
3276EB02237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
283298
324F61C9235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
284299
32C43E2322FD583B00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
285300
);
@@ -289,6 +304,7 @@
289304
isa = PBXHeadersBuildPhase;
290305
buildActionMask = 2147483647;
291306
files = (
307+
3276EB03237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
292308
324F61CA235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
293309
32C43E2422FD583C00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
294310
);
@@ -457,6 +473,7 @@
457473
isa = PBXSourcesBuildPhase;
458474
buildActionMask = 2147483647;
459475
files = (
476+
3276EB04237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */,
460477
32B933E523659A1900BB7CAD /* Transition.swift in Sources */,
461478
32C43E1722FD583700BE87F5 /* WebImage.swift in Sources */,
462479
326B848C236335400011BDFB /* ProgressIndicator.swift in Sources */,
@@ -474,6 +491,7 @@
474491
isa = PBXSourcesBuildPhase;
475492
buildActionMask = 2147483647;
476493
files = (
494+
3276EB05237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */,
477495
32B933E623659A1900BB7CAD /* Transition.swift in Sources */,
478496
32C43E1A22FD583700BE87F5 /* WebImage.swift in Sources */,
479497
326B848D236335400011BDFB /* ProgressIndicator.swift in Sources */,
@@ -491,6 +509,7 @@
491509
isa = PBXSourcesBuildPhase;
492510
buildActionMask = 2147483647;
493511
files = (
512+
3276EB06237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */,
494513
32B933E723659A1900BB7CAD /* Transition.swift in Sources */,
495514
32C43E1D22FD583800BE87F5 /* WebImage.swift in Sources */,
496515
326B848E236335400011BDFB /* ProgressIndicator.swift in Sources */,
@@ -508,6 +527,7 @@
508527
isa = PBXSourcesBuildPhase;
509528
buildActionMask = 2147483647;
510529
files = (
530+
3276EB07237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */,
511531
32B933E823659A1900BB7CAD /* Transition.swift in Sources */,
512532
32C43E2022FD583800BE87F5 /* WebImage.swift in Sources */,
513533
326B848F236335400011BDFB /* ProgressIndicator.swift in Sources */,

SDWebImageSwiftUI/Classes/AnimatedImage.swift

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,7 @@ import SDWebImageSwiftUIObjC
1414

1515
// Convenient
1616
#if os(watchOS)
17-
public typealias AnimatedImageViewWrapper = SDAnimatedImageInterface
18-
extension SDAnimatedImageInterface {
19-
var wrapped: SDAnimatedImageInterface {
20-
return self
21-
}
22-
}
17+
public typealias AnimatedImageViewWrapper = SDAnimatedImageInterfaceWrapper
2318
#endif
2419

2520
// Coordinator Life Cycle Binding Object
@@ -122,7 +117,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
122117
#else
123118
let image = SDAnimatedImage(named: name, in: bundle, compatibleWith: nil)
124119
#endif
125-
self.image = image
120+
_image = .init(wrappedValue: image)
126121
}
127122

128123
/// Create an animated image with data and scale.
@@ -139,7 +134,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
139134
public init(data: Data, scale: CGFloat = 0, isAnimating: Binding<Bool>) {
140135
self._isAnimating = isAnimating
141136
let image = SDAnimatedImage(data: data, scale: scale)
142-
self.image = image
137+
_image = .init(wrappedValue: image)
143138
}
144139

145140
#if os(macOS)
@@ -432,6 +427,8 @@ public struct AnimatedImage : PlatformViewRepresentable {
432427
// Antialiased
433428
view.shouldAntialias = self.antialiased
434429
#endif
430+
431+
view.invalidateIntrinsicContentSize()
435432
}
436433

437434
func configureView(_ view: AnimatedImageViewWrapper, context: Context) {
@@ -562,19 +559,7 @@ extension AnimatedImage {
562559
var result = self
563560
result.aspectRatio = aspectRatio
564561
result.contentMode = contentMode
565-
#if os(macOS) || os(iOS) || os(tvOS)
566562
return result.modifier(EmptyModifier()).aspectRatio(aspectRatio, contentMode: contentMode)
567-
#else
568-
return Group {
569-
if aspectRatio != nil {
570-
result.modifier(EmptyModifier()).aspectRatio(aspectRatio, contentMode: contentMode)
571-
} else {
572-
// on watchOS, there are no workaround like `AnimatedImageViewWrapper` to override `intrinsicContentSize`, so the aspect ratio is undetermined and cause sizing issues
573-
// To workaround, we do not call default implementation for this case, using original solution instead
574-
result
575-
}
576-
}
577-
#endif
578563
}
579564

580565
/// Constrains this view's dimensions to the aspect ratio of the given size.

SDWebImageSwiftUI/Classes/ObjC/SDAnimatedImageInterface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
NS_ASSUME_NONNULL_BEGIN
1313

1414
/// Do not use this class directly in WatchKit or Storyboard. This class is implementation detail and will be removed in the future.
15+
/// This is not public API at all.
1516
@interface SDAnimatedImageInterface : WKInterfaceImage
1617

1718
@property (nonatomic, assign, getter=isAnimating, readonly) BOOL animating;

SDWebImageSwiftUI/Classes/ObjC/SDAnimatedImageInterface.m

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,6 @@
1111

1212
#pragma mark - SPI
1313

14-
static UIImage * SharedEmptyImage(void) {
15-
// This is used for placeholder on `WKInterfaceImage`
16-
// Do not using `[UIImage new]` because WatchKit will ignore it
17-
static dispatch_once_t onceToken;
18-
static UIImage *image;
19-
dispatch_once(&onceToken, ^{
20-
UIColor *color = UIColor.clearColor;
21-
CGRect rect = WKInterfaceDevice.currentDevice.screenBounds;
22-
UIGraphicsBeginImageContext(rect.size);
23-
CGContextRef context = UIGraphicsGetCurrentContext();
24-
CGContextSetFillColorWithColor(context, [color CGColor]);
25-
CGContextFillRect(context, rect);
26-
image = UIGraphicsGetImageFromCurrentImageContext();
27-
UIGraphicsEndImageContext();
28-
});
29-
return image;
30-
}
31-
3214
@protocol CALayerProtocol <NSObject>
3315
@property (nullable, strong) id contents;
3416
@property CGFloat contentsScale;
@@ -43,6 +25,16 @@ @protocol UIViewProtocol <NSObject>
4325
@property (nonatomic) CGFloat alpha;
4426
@property (nonatomic, getter=isHidden) BOOL hidden;
4527
@property (nonatomic, getter=isOpaque) BOOL opaque;
28+
@property (nonatomic) CGRect frame;
29+
@property (nonatomic) CGRect bounds;
30+
@property (nonatomic) CGPoint center;
31+
@property (nonatomic, readonly) CGSize intrinsicContentSize;
32+
@property(nonatomic) NSInteger tag;
33+
34+
- (void)invalidateIntrinsicContentSize;
35+
- (void)layoutSubviews;
36+
- (CGSize)sizeThatFits:(CGSize)size;
37+
- (void)sizeToFit;
4638

4739
@end
4840

@@ -59,8 +51,9 @@ @interface WKInterfaceObject ()
5951

6052
// This is needed for dynamic created WKInterfaceObject, like `WKInterfaceMap`
6153
- (instancetype)_initForDynamicCreationWithInterfaceProperty:(NSString *)property;
54+
- (NSDictionary *)interfaceDescriptionForDynamicCreation;
6255
// This is remote UIView
63-
@property (nonatomic, strong, readonly) id<UIImageViewProtocol> _interfaceView;
56+
@property (nonatomic, strong, readwrite) id<UIViewProtocol> _interfaceView;
6457

6558
@end
6659

@@ -97,7 +90,6 @@ - (NSDictionary *)interfaceDescriptionForDynamicCreation {
9790
return @{
9891
@"type" : @"image",
9992
@"property" : self.interfaceProperty,
100-
@"image" : SharedEmptyImage()
10193
};
10294
}
10395

@@ -113,8 +105,7 @@ - (void)setImage:(UIImage *)image {
113105
self.currentFrameIndex = 0;
114106
self.currentLoopCount = 0;
115107

116-
[super setImage:image];
117-
[self _interfaceView].image = image;
108+
((id<UIImageViewProtocol>)[self _interfaceView]).image = image;
118109
if ([image.class conformsToProtocol:@protocol(SDAnimatedImage)]) {
119110
// Create animted player
120111
self.player = [SDAnimatedImagePlayer playerWithProvider:(id<SDAnimatedImage>)image];
@@ -258,4 +249,5 @@ - (void)sd_setImageWithURL:(nullable NSURL *)url
258249
}
259250

260251
@end
252+
261253
#endif
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* This file is part of the SDWebImage package.
3+
* (c) DreamPiggy <lizhuoli1126@126.com>
4+
*
5+
* For the full copyright and license information, please view the LICENSE
6+
* file that was distributed with this source code.
7+
*/
8+
9+
#import "SDAnimatedImageInterface.h"
10+
11+
#if SD_WATCH
12+
NS_ASSUME_NONNULL_BEGIN
13+
14+
/// Do not use this class directly in WatchKit or Storyboard. This class is implementation detail and will be removed in the future.
15+
/// This is not public API at all.
16+
@interface SDAnimatedImageInterfaceWrapper : WKInterfaceGroup
17+
18+
@property (nonatomic, strong, nonnull) SDAnimatedImageInterface *wrapped;
19+
20+
- (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0);
21+
22+
- (void)invalidateIntrinsicContentSize;
23+
24+
@end
25+
26+
NS_ASSUME_NONNULL_END
27+
#endif

0 commit comments

Comments
 (0)