Totally remove all previous Animated on watchOS implementation (which use WKInterfaceObject SPI)

This commit is contained in:
DreamPiggy 2019-11-29 19:49:52 +08:00
parent 0a176f4a03
commit 36bc39acce
10 changed files with 1 additions and 659 deletions

View File

@ -24,16 +24,9 @@ let package = Package(
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "SDWebImageSwiftUI",
dependencies: ["SDWebImage", "SDWebImageSwiftUIObjC"],
dependencies: ["SDWebImage"],
path: "SDWebImageSwiftUI/Classes",
exclude: ["ObjC"]
),
// This is implementation detail because SwiftPM does not support mixed Objective-C/Swift code, don't dependent this target
.target(
name: "SDWebImageSwiftUIObjC",
dependencies: ["SDWebImage"],
path: "SDWebImageSwiftUI/Classes/ObjC",
publicHeadersPath: "."
)
]
)

View File

@ -7,22 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
324F61C7235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; };
324F61C8235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; };
324F61C9235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; };
324F61CA235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; };
324F61CB235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */; };
324F61CC235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */; };
324F61CD235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */; };
324F61CE235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */; };
3253E05823879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 3253E05623879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
3253E05923879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 3253E05623879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
3253E05A23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 3253E05623879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
3253E05B23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 3253E05623879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
3253E05C23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 3253E05723879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m */; };
3253E05D23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 3253E05723879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m */; };
3253E05E23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 3253E05723879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m */; };
3253E05F23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 3253E05723879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m */; };
326B84822363350C0011BDFB /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B84812363350C0011BDFB /* Indicator.swift */; };
326B84832363350C0011BDFB /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B84812363350C0011BDFB /* Indicator.swift */; };
326B84842363350C0011BDFB /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B84812363350C0011BDFB /* Indicator.swift */; };
@ -39,14 +23,6 @@
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 */; };
@ -129,16 +105,10 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDAnimatedImageInterface.h; sourceTree = "<group>"; };
324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDAnimatedImageInterface.m; sourceTree = "<group>"; };
3253E05623879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SDAnimatedImageInterface+WebCache.h"; sourceTree = "<group>"; };
3253E05723879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SDAnimatedImageInterface+WebCache.m"; sourceTree = "<group>"; };
326B84812363350C0011BDFB /* Indicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Indicator.swift; sourceTree = "<group>"; };
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>"; };
@ -192,19 +162,6 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
324F61C4235E07EC003973B8 /* ObjC */ = {
isa = PBXGroup;
children = (
324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */,
324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */,
3253E05623879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h */,
3253E05723879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m */,
3276EAFE237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h */,
3276EAFF237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.m */,
);
path = ObjC;
sourceTree = "<group>";
};
326099472362E09E006EBB22 /* Indicator */ = {
isa = PBXGroup;
children = (
@ -258,7 +215,6 @@
children = (
32B933E323659A0700BB7CAD /* Transition */,
326099472362E09E006EBB22 /* Indicator */,
324F61C4235E07EC003973B8 /* ObjC */,
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */,
32C43DDE22FD54C600BE87F5 /* WebImage.swift */,
32C43DDF22FD54C600BE87F5 /* AnimatedImage.swift */,
@ -286,9 +242,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3253E05823879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h in Headers */,
3276EB00237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
324F61C7235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
32C43DE622FD54CD00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -297,9 +250,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3253E05923879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h in Headers */,
3276EB01237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
324F61C8235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
32C43E2222FD583A00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -308,9 +258,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3253E05A23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h in Headers */,
3276EB02237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
324F61C9235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
32C43E2322FD583B00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -319,9 +266,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3253E05B23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.h in Headers */,
3276EB03237760D800B385D4 /* SDAnimatedImageInterfaceWrapper.h in Headers */,
324F61CA235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */,
32C43E2422FD583C00BE87F5 /* SDWebImageSwiftUI.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -489,7 +433,6 @@
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 */,
@ -498,9 +441,7 @@
326E480A23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
326B8487236335110011BDFB /* ActivityIndicator.swift in Sources */,
32C43E1622FD583700BE87F5 /* ImageManager.swift in Sources */,
3253E05C23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m in Sources */,
32C43E1822FD583700BE87F5 /* AnimatedImage.swift in Sources */,
324F61CB235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -508,7 +449,6 @@
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 */,
@ -517,9 +457,7 @@
326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
326B8488236335110011BDFB /* ActivityIndicator.swift in Sources */,
32C43E1922FD583700BE87F5 /* ImageManager.swift in Sources */,
3253E05D23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m in Sources */,
32C43E1B22FD583700BE87F5 /* AnimatedImage.swift in Sources */,
324F61CC235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -527,7 +465,6 @@
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 */,
@ -536,9 +473,7 @@
326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
326B8489236335110011BDFB /* ActivityIndicator.swift in Sources */,
32C43E1C22FD583800BE87F5 /* ImageManager.swift in Sources */,
3253E05E23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m in Sources */,
32C43E1E22FD583800BE87F5 /* AnimatedImage.swift in Sources */,
324F61CD235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -546,7 +481,6 @@
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 */,
@ -555,9 +489,7 @@
326E480D23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
326B848A236335110011BDFB /* ActivityIndicator.swift in Sources */,
32C43E1F22FD583800BE87F5 /* ImageManager.swift in Sources */,
3253E05F23879A6F007ACAD8 /* SDAnimatedImageInterface+WebCache.m in Sources */,
32C43E2122FD583800BE87F5 /* AnimatedImage.swift in Sources */,
324F61CE235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -8,14 +8,6 @@
import Foundation
import SDWebImage
#if canImport(SDWebImageSwiftUIObjC)
import SDWebImageSwiftUIObjC
#endif
#if os(watchOS)
/// Use wrapper to solve the `WKInterfaceImage` aspect issue (SwiftUI's Bug)
public typealias AnimatedImageViewWrapper = SDAnimatedImageInterfaceWrapper
#endif
#if !os(watchOS)

View File

@ -1,31 +0,0 @@
/*
* 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 SDAnimatedImageInterface (WebCache)
@property (nonatomic, strong, nullable) NSString *sd_imageName;
@property (nonatomic, strong, nullable) NSData *sd_imageData;
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
context:(nullable SDWebImageContext *)context
progress:(nullable SDImageLoaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock;
@end
NS_ASSUME_NONNULL_END
#endif

View File

@ -1,62 +0,0 @@
/*
* 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+WebCache.h"
#if SD_WATCH
#import <objc/runtime.h>
@implementation SDAnimatedImageInterface (WebCache)
- (NSString *)sd_imageName {
return objc_getAssociatedObject(self, @selector(sd_imageName));
}
- (void)setSd_imageName:(NSString *)sd_imageName {
objc_setAssociatedObject(self, @selector(sd_imageName), sd_imageName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSData *)sd_imageData {
return objc_getAssociatedObject(self, @selector(sd_imageData));
}
- (void)setSd_imageData:(NSData *)sd_imageData {
objc_setAssociatedObject(self, @selector(sd_imageData), sd_imageData, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
context:(nullable SDWebImageContext *)context
progress:(nullable SDImageLoaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock {
Class animatedImageClass = [SDAnimatedImage class];
SDWebImageMutableContext *mutableContext;
if (context) {
mutableContext = [context mutableCopy];
} else {
mutableContext = [NSMutableDictionary dictionary];
}
mutableContext[SDWebImageContextAnimatedImageClass] = animatedImageClass;
[self sd_internalSetImageWithURL:url
placeholderImage:placeholder
options:options
context:mutableContext
setImageBlock:nil
progress:progressBlock
completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
if (completedBlock) {
completedBlock(image, error, cacheType, imageURL);
}
}];
}
@end
#endif

View File

@ -1,35 +0,0 @@
/*
* 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 SDWebImage;
#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 SDAnimatedImageInterface : WKInterfaceImage
@property (nonatomic, strong, readonly, nullable) UIImage *image;
@property (nonatomic, assign, getter=isAnimating, readonly) BOOL animating;
@property (nonatomic, assign) SDImageScaleMode contentMode;
@property (nonatomic, strong, nullable) NSNumber *animationRepeatCount;
@property (nonatomic, copy) NSRunLoopMode runLoopMode;
@property (nonatomic, assign) BOOL resetFrameIndexWhenStopped;
@property (nonatomic, assign) BOOL clearBufferWhenStopped;
@property (nonatomic, assign) double playbackRate;
- (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0);
/// Trigger the animation check when view appears/disappears
- (void)updateAnimation;
@end
NS_ASSUME_NONNULL_END
#endif

View File

@ -1,214 +0,0 @@
/*
* 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
#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
@interface SDAnimatedImageInterface ()
@property (nonatomic, strong, readwrite) UIImage *currentFrame;
@property (nonatomic, assign, readwrite) NSUInteger currentFrameIndex;
@property (nonatomic, assign, readwrite) NSUInteger currentLoopCount;
@property (nonatomic, assign, getter=isAnimating, readwrite) BOOL animating;
@property (nonatomic, assign) BOOL shouldAnimate;
@property (nonatomic, strong) SDAnimatedImagePlayer *player; // The animation player.
@property (nonatomic) id<CALayerProtocol> imageViewLayer; // The actual rendering layer.
@end
@implementation SDAnimatedImageInterface
- (instancetype)init {
Class cls = [self class];
NSString *UUID = [NSUUID UUID].UUIDString;
NSString *property = [NSString stringWithFormat:@"%@_%@", cls, UUID];
self = [self _initForDynamicCreationWithInterfaceProperty:property];
if (self) {
self.runLoopMode = NSRunLoopCommonModes;
self.playbackRate = 1.0;
}
return self;
}
- (NSDictionary *)interfaceDescriptionForDynamicCreation {
// This is called by WatchKit
return @{
@"type" : @"image",
@"property" : self.interfaceProperty,
};
}
- (void)setImage:(UIImage *)image {
if (_image == image) {
return;
}
_image = image;
// Stop animating
self.player = nil;
self.currentFrame = nil;
self.currentFrameIndex = 0;
self.currentLoopCount = 0;
((id<UIImageViewProtocol>)[self _interfaceView]).image = image;
if ([image.class conformsToProtocol:@protocol(SDAnimatedImage)]) {
// Create animted player
self.player = [SDAnimatedImagePlayer playerWithProvider:(id<SDAnimatedImage>)image];
if (!self.player) {
// animated player nil means the image format is not supported, or frame count <= 1
return;
}
// Custom Loop Count
if (self.animationRepeatCount != nil) {
self.player.totalLoopCount = self.animationRepeatCount.unsignedIntegerValue;
}
// RunLoop Mode
self.player.runLoopMode = self.runLoopMode;
// Play Rate
self.player.playbackRate = self.playbackRate;
// Setup handler
__weak typeof(self) wself = self;
self.player.animationFrameHandler = ^(NSUInteger index, UIImage * frame) {
__strong typeof(self) sself = wself;
sself.currentFrameIndex = index;
sself.currentFrame = frame;
[sself displayLayer:sself.imageViewLayer];
};
self.player.animationLoopHandler = ^(NSUInteger loopCount) {
__strong typeof(self) sself = wself;
sself.currentLoopCount = loopCount;
};
// Start animating
[self startAnimating];
[self displayLayer:self.imageViewLayer];
}
}
- (void)updateAnimation {
[self updateShouldAnimate];
if (self.shouldAnimate && self.isAnimating) {
[self startAnimating];
} else {
[self stopAnimating];
}
}
- (void)displayLayer:(id<CALayerProtocol>)layer {
UIImage *currentFrame = self.currentFrame;
if (currentFrame) {
layer.contentsScale = currentFrame.scale;
layer.contents = (__bridge id)currentFrame.CGImage;
}
}
// on watchOS, it's the native imageView itself's layer
- (id<CALayerProtocol>)imageViewLayer {
return [self _interfaceView].layer;
}
- (void)updateShouldAnimate
{
id<UIViewProtocol> view = [self _interfaceView];
BOOL isVisible = view.window && view.superview && ![view isHidden] && view.alpha > 0.0;
self.shouldAnimate = self.player && isVisible;
}
- (void)startAnimating {
self.animating = YES;
if (self.player) {
[self updateShouldAnimate];
if (self.shouldAnimate) {
[self.player startPlaying];
}
} else if (_image.images.count > 0) {
[super startAnimating];
}
}
- (void)stopAnimating {
self.animating = NO;
if (self.player) {
if (self.resetFrameIndexWhenStopped) {
[self.player stopPlaying];
} else {
[self.player pausePlaying];
}
if (self.clearBufferWhenStopped) {
[self.player clearFrameBuffer];
}
} else if (_image.images.count > 0) {
[super stopAnimating];
}
}
- (void)setContentMode:(SDImageScaleMode)contentMode {
[self _interfaceView].contentMode = contentMode;
}
- (SDImageScaleMode)contentMode {
return [self _interfaceView].contentMode;
}
@end
#endif

View File

@ -1,27 +0,0 @@
/*
* 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);
- (void)invalidateIntrinsicContentSize;
@end
NS_ASSUME_NONNULL_END
#endif

View File

@ -1,203 +0,0 @@
/*
* 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, CGSize))objc_msgSend)(self, NSSelectorFromString(SDAnimatedImageInterfaceWrapperSEL_sizeThatFits), size);
}
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;
}
- (void)invalidateIntrinsicContentSize {
[self._interfaceView invalidateIntrinsicContentSize];
}
@end
#endif

View File

@ -15,6 +15,3 @@ FOUNDATION_EXPORT double SDWebImageSwiftUIVersionNumber;
FOUNDATION_EXPORT const unsigned char SDWebImageSwiftUIVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <SDWebImageSwiftUI/PublicHeader.h>
#import <SDWebImageSwiftUI/SDAnimatedImageInterface.h>
#import <SDWebImageSwiftUI/SDAnimatedImageInterface+WebCache.h>
#import <SDWebImageSwiftUI/SDAnimatedImageInterfaceWrapper.h>