Skip to content

Commit 6e32a73

Browse files
committed
Move the watchOS wrapper hack into another file, make it easy to distinguish
1 parent a2a54ec commit 6e32a73

File tree

7 files changed

+249
-155
lines changed

7 files changed

+249
-155
lines changed

Example/SDWebImageSwiftUIDemo/ContentView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,12 @@ struct ContentView: View {
9696
*/
9797
.transition(.fade)
9898
.resizable()
99-
.scaledToFit()
99+
.scaledToFill()
100100
.frame(width: CGFloat(100), height: CGFloat(100), alignment: .center)
101101
#else
102102
AnimatedImage(url: URL(string:url))
103103
.resizable()
104-
.scaledToFit()
104+
.scaledToFill()
105105
.frame(width: CGFloat(100), height: CGFloat(100), alignment: .center)
106106
#endif
107107
} else {

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/ObjC/SDAnimatedImageInterface.h

Lines changed: 1 addition & 8 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;
@@ -29,13 +30,5 @@ NS_ASSUME_NONNULL_BEGIN
2930

3031
@end
3132

32-
@interface SDAnimatedImageInterfaceWrapper : WKInterfaceGroup
33-
34-
@property (nonatomic, strong, nonnull) SDAnimatedImageInterface *wrapped;
35-
36-
- (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0);
37-
38-
@end
39-
4033
NS_ASSUME_NONNULL_END
4134
#endif

SDWebImageSwiftUI/Classes/ObjC/SDAnimatedImageInterface.m

Lines changed: 1 addition & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99
#import "SDAnimatedImageInterface.h"
1010
#if SD_WATCH
1111

12-
#import <objc/runtime.h>
13-
#import <objc/message.h>
14-
1512
#pragma mark - SPI
1613

1714
@protocol CALayerProtocol <NSObject>
@@ -31,16 +28,10 @@ @protocol UIViewProtocol <NSObject>
3128
@property (nonatomic) CGRect frame;
3229
@property (nonatomic) CGRect bounds;
3330
@property (nonatomic) CGPoint center;
34-
@property (nonatomic) BOOL clipsToBounds;
3531
@property (nonatomic, readonly) CGSize intrinsicContentSize;
3632
@property(nonatomic) NSInteger tag;
3733

3834
- (void)invalidateIntrinsicContentSize;
39-
- (void)drawRect:(CGRect)rect;
40-
- (void)setNeedsDisplay;
41-
- (void)setNeedsDisplayInRect:(CGRect)rect;
42-
- (void)addSubview:(id<UIViewProtocol>)view;
43-
- (void)removeFromSuperview;
4435
- (void)layoutSubviews;
4536
- (CGSize)sizeThatFits:(CGSize)size;
4637
- (void)sizeToFit;
@@ -60,6 +51,7 @@ @interface WKInterfaceObject ()
6051

6152
// This is needed for dynamic created WKInterfaceObject, like `WKInterfaceMap`
6253
- (instancetype)_initForDynamicCreationWithInterfaceProperty:(NSString *)property;
54+
- (NSDictionary *)interfaceDescriptionForDynamicCreation;
6355
// This is remote UIView
6456
@property (nonatomic, strong, readwrite) id<UIViewProtocol> _interfaceView;
6557

@@ -258,140 +250,4 @@ - (void)sd_setImageWithURL:(nullable NSURL *)url
258250

259251
@end
260252

261-
262-
#define SDAnimatedImageInterfaceWrapperTag 123456789
263-
#define SDAnimatedImageInterfaceWrapperSEL_layoutSubviews @"SDAnimatedImageInterfaceWrapper_layoutSubviews"
264-
#define SDAnimatedImageInterfaceWrapperSEL_sizeThatFits @" SDAnimatedImageInterfaceWrapper_sizeThatFits:"
265-
266-
// This using hook to implements the same logic like AnimatedImageViewWrapper.swift
267-
static CGSize intrinsicContentSizeIMP(id<UIViewProtocol> self, SEL _cmd) {
268-
struct objc_super superClass = {
269-
self,
270-
[self superclass]
271-
};
272-
NSUInteger tag = self.tag;
273-
id<UIViewProtocol> interfaceView = self.subviews.firstObject;
274-
if (tag != SDAnimatedImageInterfaceWrapperTag || !interfaceView) {
275-
return ((CGSize(*)(id, SEL))objc_msgSendSuper)((__bridge id)(&superClass), _cmd);
276-
}
277-
CGSize size = interfaceView.intrinsicContentSize;
278-
if (size.width > 0 && size.height > 0) {
279-
CGFloat aspectRatio = size.height / size.width;
280-
return CGSizeMake(1, 1 * aspectRatio);
281-
} else {
282-
return CGSizeMake(-1, -1);
283-
}
284-
}
285-
286-
static void layoutSubviewsIMP(id<UIViewProtocol> self, SEL _cmd) {
287-
struct objc_super superClass = {
288-
self,
289-
[self superclass]
290-
};
291-
NSUInteger tag = self.tag;
292-
id<UIViewProtocol> interfaceView = self.subviews.firstObject;
293-
if (tag != SDAnimatedImageInterfaceWrapperTag || !interfaceView) {
294-
((void(*)(id, SEL))objc_msgSend)(self, NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_layoutSubviews));
295-
return;
296-
}
297-
((void(*)(id, SEL))objc_msgSendSuper)((__bridge id)(&superClass), _cmd);
298-
interfaceView.frame = self.bounds;
299-
}
300-
301-
// This is suck that SwiftUI on watchOS will call extra sizeThatFits, we should always input size (already calculated with aspectRatio)
302-
// iOS's wrapper don't need this
303-
static CGSize sizeThatFitsIMP(id<UIViewProtocol> self, SEL _cmd, CGSize size) {
304-
NSUInteger tag = self.tag;
305-
id<UIViewProtocol> interfaceView = self.subviews.firstObject;
306-
if (tag != SDAnimatedImageInterfaceWrapperTag || !interfaceView) {
307-
return ((CGSize(*)(id, SEL))objc_msgSend)(self, NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_sizeThatFits));
308-
}
309-
return size;
310-
}
311-
312-
@implementation SDAnimatedImageInterfaceWrapper
313-
314-
+ (void)load {
315-
static dispatch_once_t onceToken;
316-
dispatch_once(&onceToken, ^{
317-
Class class = NSClassFromString(@"SPInterfaceGroupView");
318-
// Implements `intrinsicContentSize`
319-
SEL selector = @selector(intrinsicContentSize);
320-
Method method = class_getInstanceMethod(class, selector);
321-
322-
BOOL didAddMethod =
323-
class_addMethod(class,
324-
selector,
325-
(IMP)intrinsicContentSizeIMP,
326-
method_getTypeEncoding(method));
327-
if (!didAddMethod) {
328-
NSAssert(NO, @"SDAnimatedImageInterfaceWrapper will not work as expected.");
329-
}
330-
331-
// Override `layoutSubviews`
332-
SEL originalSelector = @selector(layoutSubviews);
333-
SEL swizzledSelector = NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_layoutSubviews);
334-
Method originalMethod = class_getInstanceMethod(class, originalSelector);
335-
336-
didAddMethod =
337-
class_addMethod(class,
338-
swizzledSelector,
339-
(IMP)layoutSubviewsIMP,
340-
method_getTypeEncoding(originalMethod));
341-
if (!didAddMethod) {
342-
NSAssert(NO, @"SDAnimatedImageInterfaceWrapper will not work as expected.");
343-
} else {
344-
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
345-
method_exchangeImplementations(originalMethod, swizzledMethod);
346-
}
347-
348-
// Override `sizeThatFits:`
349-
originalSelector = @selector(sizeThatFits:);
350-
swizzledSelector = NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_sizeThatFits);
351-
originalMethod = class_getInstanceMethod(class, originalSelector);
352-
353-
didAddMethod =
354-
class_addMethod(class,
355-
swizzledSelector,
356-
(IMP)sizeThatFitsIMP,
357-
method_getTypeEncoding(originalMethod));
358-
if (!didAddMethod) {
359-
NSAssert(NO, @"SDAnimatedImageInterfaceWrapper will not work as expected.");
360-
} else {
361-
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
362-
method_exchangeImplementations(originalMethod, swizzledMethod);
363-
}
364-
});
365-
}
366-
367-
- (instancetype)init {
368-
Class cls = [self class];
369-
NSString *UUID = [NSUUID UUID].UUIDString;
370-
NSString *property = [NSString stringWithFormat:@"%@_%@", cls, UUID];
371-
self = [self _initForDynamicCreationWithInterfaceProperty:property];
372-
if (self) {
373-
self.wrapped = [[SDAnimatedImageInterface alloc] init];
374-
}
375-
return self;
376-
}
377-
378-
- (NSDictionary *)interfaceDescriptionForDynamicCreation {
379-
// This is called by WatchKit to provide default value
380-
return @{
381-
@"type" : @"group",
382-
@"property" : self.interfaceProperty,
383-
@"radius" : @(0),
384-
@"items": @[self.wrapped.interfaceDescriptionForDynamicCreation], // This will create the native view and added to subview
385-
};
386-
}
387-
388-
- (void)set_interfaceView:(id<UIViewProtocol>)interfaceView {
389-
// This is called by WatchKit when native view created
390-
[super set_interfaceView:interfaceView];
391-
// Bind the interface object and native view
392-
interfaceView.tag = SDAnimatedImageInterfaceWrapperTag;
393-
self.wrapped._interfaceView = interfaceView.subviews.firstObject;
394-
}
395-
396-
@end
397253
#endif
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
@end
23+
24+
NS_ASSUME_NONNULL_END
25+
#endif

0 commit comments

Comments
 (0)