Move the watchOS wrapper hack into another file, make it easy to distinguish from other code to maintain

This commit is contained in:
DreamPiggy 2019-11-10 05:12:29 +08:00
parent a2a54ec329
commit e01fa4047b
6 changed files with 247 additions and 153 deletions

View File

@ -31,6 +31,14 @@
326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
326E480D23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
3276EB00237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
3276EB01237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
3276EB02237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
3276EB03237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
3276EB04237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */; };
3276EB05237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */; };
3276EB06237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */; };
3276EB07237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */; };
32B933E523659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
32B933E623659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
32B933E723659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
@ -119,6 +127,8 @@
326B8486236335110011BDFB /* ActivityIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicator.swift; sourceTree = "<group>"; };
326B848B236335400011BDFB /* ProgressIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressIndicator.swift; sourceTree = "<group>"; };
326E480923431C0F00C633E9 /* ImageViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewWrapper.swift; sourceTree = "<group>"; };
3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDAnimatedImageInterfaceWrapper.h; sourceTree = "<group>"; };
3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDAnimatedImageInterfaceWrapper.m; sourceTree = "<group>"; };
32B933E423659A1900BB7CAD /* Transition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transition.swift; sourceTree = "<group>"; };
32C43DCC22FD540D00BE87F5 /* SDWebImageSwiftUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSwiftUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageManager.swift; sourceTree = "<group>"; };
@ -177,6 +187,8 @@
children = (
324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */,
324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */,
3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */,
3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */,
);
path = ObjC;
sourceTree = "<group>";
@ -262,6 +274,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3276EB00237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
324F61C7235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
32C43DE622FD54CD00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
);
@ -271,6 +284,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3276EB01237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
324F61C8235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
32C43E2222FD583A00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
);
@ -280,6 +294,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3276EB02237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
324F61C9235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
32C43E2322FD583B00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
);
@ -289,6 +304,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3276EB03237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
324F61CA235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
32C43E2422FD583C00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
);
@ -457,6 +473,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3276EB04237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */,
32B933E523659A1900BB7CAD /* Transition.swift in Sources */,
32C43E1722FD583700BE87F5 /* WebImage.swift in Sources */,
326B848C236335400011BDFB /* ProgressIndicator.swift in Sources */,
@ -474,6 +491,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3276EB05237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */,
32B933E623659A1900BB7CAD /* Transition.swift in Sources */,
32C43E1A22FD583700BE87F5 /* WebImage.swift in Sources */,
326B848D236335400011BDFB /* ProgressIndicator.swift in Sources */,
@ -491,6 +509,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3276EB06237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */,
32B933E723659A1900BB7CAD /* Transition.swift in Sources */,
32C43E1D22FD583800BE87F5 /* WebImage.swift in Sources */,
326B848E236335400011BDFB /* ProgressIndicator.swift in Sources */,
@ -508,6 +527,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3276EB07237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m in Sources */,
32B933E823659A1900BB7CAD /* Transition.swift in Sources */,
32C43E2022FD583800BE87F5 /* WebImage.swift in Sources */,
326B848F236335400011BDFB /* ProgressIndicator.swift in Sources */,

View File

@ -12,6 +12,7 @@
NS_ASSUME_NONNULL_BEGIN
/// Do not use this class directly in WatchKit or Storyboard. This class is implementation detail and will be removed in the future.
/// This is not public API at all.
@interface SDAnimatedImageInterface : WKInterfaceImage
@property (nonatomic, assign, getter=isAnimating, readonly) BOOL animating;
@ -29,13 +30,5 @@ NS_ASSUME_NONNULL_BEGIN
@end
@interface SDAnimatedImageInterfaceWrapper : WKInterfaceGroup
@property (nonatomic, strong, nonnull) SDAnimatedImageInterface *wrapped;
- (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0);
@end
NS_ASSUME_NONNULL_END
#endif

View File

@ -9,9 +9,6 @@
#import "SDAnimatedImageInterface.h"
#if SD_WATCH
#import <objc/runtime.h>
#import <objc/message.h>
#pragma mark - SPI
@protocol CALayerProtocol <NSObject>
@ -31,16 +28,10 @@
@property (nonatomic) CGRect frame;
@property (nonatomic) CGRect bounds;
@property (nonatomic) CGPoint center;
@property (nonatomic) BOOL clipsToBounds;
@property (nonatomic, readonly) CGSize intrinsicContentSize;
@property(nonatomic) NSInteger tag;
- (void)invalidateIntrinsicContentSize;
- (void)drawRect:(CGRect)rect;
- (void)setNeedsDisplay;
- (void)setNeedsDisplayInRect:(CGRect)rect;
- (void)addSubview:(id<UIViewProtocol>)view;
- (void)removeFromSuperview;
- (void)layoutSubviews;
- (CGSize)sizeThatFits:(CGSize)size;
- (void)sizeToFit;
@ -60,6 +51,7 @@
// This is needed for dynamic created WKInterfaceObject, like `WKInterfaceMap`
- (instancetype)_initForDynamicCreationWithInterfaceProperty:(NSString *)property;
- (NSDictionary *)interfaceDescriptionForDynamicCreation;
// This is remote UIView
@property (nonatomic, strong, readwrite) id<UIViewProtocol> _interfaceView;
@ -258,140 +250,4 @@
@end
#define SDAnimatedImageInterfaceWrapperTag 123456789
#define SDAnimatedImageInterfaceWrapperSEL_layoutSubviews @"SDAnimatedImageInterfaceWrapper_layoutSubviews"
#define SDAnimatedImageInterfaceWrapperSEL_sizeThatFits @" SDAnimatedImageInterfaceWrapper_sizeThatFits:"
// This using hook to implements the same logic like AnimatedImageViewWrapper.swift
static CGSize intrinsicContentSizeIMP(id<UIViewProtocol> self, SEL _cmd) {
struct objc_super superClass = {
self,
[self superclass]
};
NSUInteger tag = self.tag;
id<UIViewProtocol> interfaceView = self.subviews.firstObject;
if (tag != SDAnimatedImageInterfaceWrapperTag || !interfaceView) {
return ((CGSize(*)(id, SEL))objc_msgSendSuper)((__bridge id)(&superClass), _cmd);
}
CGSize size = interfaceView.intrinsicContentSize;
if (size.width > 0 && size.height > 0) {
CGFloat aspectRatio = size.height / size.width;
return CGSizeMake(1, 1 * aspectRatio);
} else {
return CGSizeMake(-1, -1);
}
}
static void layoutSubviewsIMP(id<UIViewProtocol> self, SEL _cmd) {
struct objc_super superClass = {
self,
[self superclass]
};
NSUInteger tag = self.tag;
id<UIViewProtocol> interfaceView = self.subviews.firstObject;
if (tag != SDAnimatedImageInterfaceWrapperTag || !interfaceView) {
((void(*)(id, SEL))objc_msgSend)(self, NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_layoutSubviews));
return;
}
((void(*)(id, SEL))objc_msgSendSuper)((__bridge id)(&superClass), _cmd);
interfaceView.frame = self.bounds;
}
// This is suck that SwiftUI on watchOS will call extra sizeThatFits, we should always input size (already calculated with aspectRatio)
// iOS's wrapper don't need this
static CGSize sizeThatFitsIMP(id<UIViewProtocol> self, SEL _cmd, CGSize size) {
NSUInteger tag = self.tag;
id<UIViewProtocol> interfaceView = self.subviews.firstObject;
if (tag != SDAnimatedImageInterfaceWrapperTag || !interfaceView) {
return ((CGSize(*)(id, SEL))objc_msgSend)(self, NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_sizeThatFits));
}
return size;
}
@implementation SDAnimatedImageInterfaceWrapper
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = NSClassFromString(@"SPInterfaceGroupView");
// Implements `intrinsicContentSize`
SEL selector = @selector(intrinsicContentSize);
Method method = class_getInstanceMethod(class, selector);
BOOL didAddMethod =
class_addMethod(class,
selector,
(IMP)intrinsicContentSizeIMP,
method_getTypeEncoding(method));
if (!didAddMethod) {
NSAssert(NO, @"SDAnimatedImageInterfaceWrapper will not work as expected.");
}
// Override `layoutSubviews`
SEL originalSelector = @selector(layoutSubviews);
SEL swizzledSelector = NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_layoutSubviews);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
didAddMethod =
class_addMethod(class,
swizzledSelector,
(IMP)layoutSubviewsIMP,
method_getTypeEncoding(originalMethod));
if (!didAddMethod) {
NSAssert(NO, @"SDAnimatedImageInterfaceWrapper will not work as expected.");
} else {
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
// Override `sizeThatFits:`
originalSelector = @selector(sizeThatFits:);
swizzledSelector = NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_sizeThatFits);
originalMethod = class_getInstanceMethod(class, originalSelector);
didAddMethod =
class_addMethod(class,
swizzledSelector,
(IMP)sizeThatFitsIMP,
method_getTypeEncoding(originalMethod));
if (!didAddMethod) {
NSAssert(NO, @"SDAnimatedImageInterfaceWrapper will not work as expected.");
} else {
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (instancetype)init {
Class cls = [self class];
NSString *UUID = [NSUUID UUID].UUIDString;
NSString *property = [NSString stringWithFormat:@"%@_%@", cls, UUID];
self = [self _initForDynamicCreationWithInterfaceProperty:property];
if (self) {
self.wrapped = [[SDAnimatedImageInterface alloc] init];
}
return self;
}
- (NSDictionary *)interfaceDescriptionForDynamicCreation {
// This is called by WatchKit to provide default value
return @{
@"type" : @"group",
@"property" : self.interfaceProperty,
@"radius" : @(0),
@"items": @[self.wrapped.interfaceDescriptionForDynamicCreation], // This will create the native view and added to subview
};
}
- (void)set_interfaceView:(id<UIViewProtocol>)interfaceView {
// This is called by WatchKit when native view created
[super set_interfaceView:interfaceView];
// Bind the interface object and native view
interfaceView.tag = SDAnimatedImageInterfaceWrapperTag;
self.wrapped._interfaceView = interfaceView.subviews.firstObject;
}
@end
#endif

View File

@ -0,0 +1,25 @@
/*
* This file is part of the SDWebImage package.
* (c) DreamPiggy <lizhuoli1126@126.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#import "SDAnimatedImageInterface.h"
#if SD_WATCH
NS_ASSUME_NONNULL_BEGIN
/// Do not use this class directly in WatchKit or Storyboard. This class is implementation detail and will be removed in the future.
/// This is not public API at all.
@interface SDAnimatedImageInterfaceWrapper : WKInterfaceGroup
@property (nonatomic, strong, nonnull) SDAnimatedImageInterface *wrapped;
- (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0);
@end
NS_ASSUME_NONNULL_END
#endif

View File

@ -0,0 +1,199 @@
/*
* This file is part of the SDWebImage package.
* (c) DreamPiggy <lizhuoli1126@126.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#import "SDAnimatedImageInterfaceWrapper.h"
#if SD_WATCH
#import <objc/runtime.h>
#import <objc/message.h>
#pragma mark - SPI
@protocol CALayerProtocol <NSObject>
@property (nullable, strong) id contents;
@property CGFloat contentsScale;
@end
@protocol UIViewProtocol <NSObject>
@property (nonatomic, strong, readonly) id<CALayerProtocol> layer;
@property (nonatomic, assign) SDImageScaleMode contentMode;
@property (nonatomic, readonly) id<UIViewProtocol> superview;
@property (nonatomic, readonly, copy) NSArray<id<UIViewProtocol>> *subviews;
@property (nonatomic, readonly) id window;
@property (nonatomic) CGFloat alpha;
@property (nonatomic, getter=isHidden) BOOL hidden;
@property (nonatomic, getter=isOpaque) BOOL opaque;
@property (nonatomic) CGRect frame;
@property (nonatomic) CGRect bounds;
@property (nonatomic) CGPoint center;
@property (nonatomic, readonly) CGSize intrinsicContentSize;
@property(nonatomic) NSInteger tag;
- (void)invalidateIntrinsicContentSize;
- (void)layoutSubviews;
- (CGSize)sizeThatFits:(CGSize)size;
- (void)sizeToFit;
@end
@protocol UIImageViewProtocol <UIViewProtocol>
@property (nullable, nonatomic, strong) UIImage *image;
- (void)startAnimating;
- (void)stopAnimating;
@property (nonatomic, readonly, getter=isAnimating) BOOL animating;
@end
@interface WKInterfaceObject ()
// This is needed for dynamic created WKInterfaceObject, like `WKInterfaceMap`
- (instancetype)_initForDynamicCreationWithInterfaceProperty:(NSString *)property;
- (NSDictionary *)interfaceDescriptionForDynamicCreation;
// This is remote UIView
@property (nonatomic, strong, readwrite) id<UIViewProtocol> _interfaceView;
@end
#define SDAnimatedImageInterfaceWrapperTag 123456789
#define SDAnimatedImageInterfaceWrapperSEL_layoutSubviews @"SDAnimatedImageInterfaceWrapper_layoutSubviews"
#define SDAnimatedImageInterfaceWrapperSEL_sizeThatFits @" SDAnimatedImageInterfaceWrapper_sizeThatFits:"
// This using hook to implements the same logic like AnimatedImageViewWrapper.swift
static CGSize intrinsicContentSizeIMP(id<UIViewProtocol> self, SEL _cmd) {
struct objc_super superClass = {
self,
[self superclass]
};
NSUInteger tag = self.tag;
id<UIViewProtocol> interfaceView = self.subviews.firstObject;
if (tag != SDAnimatedImageInterfaceWrapperTag || !interfaceView) {
return ((CGSize(*)(id, SEL))objc_msgSendSuper)((__bridge id)(&superClass), _cmd);
}
CGSize size = interfaceView.intrinsicContentSize;
if (size.width > 0 && size.height > 0) {
CGFloat aspectRatio = size.height / size.width;
return CGSizeMake(1, 1 * aspectRatio);
} else {
return CGSizeMake(-1, -1);
}
}
static void layoutSubviewsIMP(id<UIViewProtocol> self, SEL _cmd) {
struct objc_super superClass = {
self,
[self superclass]
};
NSUInteger tag = self.tag;
id<UIViewProtocol> interfaceView = self.subviews.firstObject;
if (tag != SDAnimatedImageInterfaceWrapperTag || !interfaceView) {
((void(*)(id, SEL))objc_msgSend)(self, NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_layoutSubviews));
return;
}
((void(*)(id, SEL))objc_msgSendSuper)((__bridge id)(&superClass), _cmd);
interfaceView.frame = self.bounds;
}
// This is suck that SwiftUI on watchOS will call extra sizeThatFits, we should always return input size (already calculated with aspectRatio)
// iOS's wrapper don't need this. Apple should provide the public API on View protocol to specify `intrinsicContentSize` or `intrinsicAspectRatio`
static CGSize sizeThatFitsIMP(id<UIViewProtocol> self, SEL _cmd, CGSize size) {
NSUInteger tag = self.tag;
id<UIViewProtocol> interfaceView = self.subviews.firstObject;
if (tag != SDAnimatedImageInterfaceWrapperTag || !interfaceView) {
return ((CGSize(*)(id, SEL))objc_msgSend)(self, NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_sizeThatFits));
}
return size;
}
@implementation SDAnimatedImageInterfaceWrapper
/// Use wrapper to solve tne watchOS `WKInterfaceImage` frame size become image size issue, as well as aspect ratio issue (SwiftUI's Bug)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = NSClassFromString(@"SPInterfaceGroupView");
// Implements `intrinsicContentSize`
SEL selector = @selector(intrinsicContentSize);
Method method = class_getInstanceMethod(class, selector);
BOOL didAddMethod =
class_addMethod(class,
selector,
(IMP)intrinsicContentSizeIMP,
method_getTypeEncoding(method));
if (!didAddMethod) {
NSAssert(NO, @"SDAnimatedImageInterfaceWrapper will not work as expected.");
}
// Override `layoutSubviews`
SEL originalSelector = @selector(layoutSubviews);
SEL swizzledSelector = NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_layoutSubviews);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
didAddMethod =
class_addMethod(class,
swizzledSelector,
(IMP)layoutSubviewsIMP,
method_getTypeEncoding(originalMethod));
if (!didAddMethod) {
NSAssert(NO, @"SDAnimatedImageInterfaceWrapper will not work as expected.");
} else {
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
// Override `sizeThatFits:`
originalSelector = @selector(sizeThatFits:);
swizzledSelector = NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_sizeThatFits);
originalMethod = class_getInstanceMethod(class, originalSelector);
didAddMethod =
class_addMethod(class,
swizzledSelector,
(IMP)sizeThatFitsIMP,
method_getTypeEncoding(originalMethod));
if (!didAddMethod) {
NSAssert(NO, @"SDAnimatedImageInterfaceWrapper will not work as expected.");
} else {
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (instancetype)init {
Class cls = [self class];
NSString *UUID = [NSUUID UUID].UUIDString;
NSString *property = [NSString stringWithFormat:@"%@_%@", cls, UUID];
self = [self _initForDynamicCreationWithInterfaceProperty:property];
if (self) {
self.wrapped = [[SDAnimatedImageInterface alloc] init];
}
return self;
}
- (NSDictionary *)interfaceDescriptionForDynamicCreation {
// This is called by WatchKit to provide default value
return @{
@"type" : @"group",
@"property" : self.interfaceProperty,
@"radius" : @(0),
@"items": @[self.wrapped.interfaceDescriptionForDynamicCreation], // This will create the native view and added to subview
};
}
- (void)set_interfaceView:(id<UIViewProtocol>)interfaceView {
// This is called by WatchKit when native view created
[super set_interfaceView:interfaceView];
// Bind the interface object and native view
interfaceView.tag = SDAnimatedImageInterfaceWrapperTag;
self.wrapped._interfaceView = interfaceView.subviews.firstObject;
}
@end
#endif

View File

@ -8,6 +8,7 @@
#import <Foundation/Foundation.h>
#import <SDWebImageSwiftUI/SDAnimatedImageInterface.h>
#import <SDWebImageSwiftUI/SDAnimatedImageInterfaceWrapper.h>
//! Project version number for SDWebImageSwiftUI.
FOUNDATION_EXPORT double SDWebImageSwiftUIVersionNumber;