From bfb48ac1e86b30f352fa1195c905dfa0671dfbf9 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sun, 6 Oct 2019 18:46:19 +0800 Subject: [PATCH 01/17] Temp for watchOS AnimatedImage support, using massive private API, still contains small issues --- Example/Podfile.lock | 12 +- .../SDWebImageSwiftUIDemo/ContentView.swift | 3 + .../SDWebImageSwiftUIDemo/DetailView.swift | 18 +- SDWebImageSwiftUI.xcodeproj/project.pbxproj | 36 ++++ SDWebImageSwiftUI/Classes/AnimatedImage.swift | 33 ++- .../Classes/SDAnimatedImageInterface.h | 19 ++ .../Classes/SDAnimatedImageInterface.m | 198 ++++++++++++++++++ SDWebImageSwiftUI/Module/SDWebImageSwiftUI.h | 1 + 8 files changed, 290 insertions(+), 30 deletions(-) create mode 100644 SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h create mode 100644 SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 207726e9..1638bdb2 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -8,9 +8,9 @@ PODS: - libwebp/mux (1.0.3): - libwebp/demux - libwebp/webp (1.0.3) - - SDWebImage (5.2.3): - - SDWebImage/Core (= 5.2.3) - - SDWebImage/Core (5.2.3) + - SDWebImage (5.2.2): + - SDWebImage/Core (= 5.2.2) + - SDWebImage/Core (5.2.2) - SDWebImageSwiftUI (0.3.1): - SDWebImage (~> 5.1) - SDWebImageWebPCoder (0.2.5): @@ -22,7 +22,7 @@ DEPENDENCIES: - SDWebImageWebPCoder SPEC REPOS: - trunk: + https://github.com/cocoapods/specs.git: - libwebp - SDWebImage - SDWebImageWebPCoder @@ -33,10 +33,10 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: libwebp: 057912d6d0abfb6357d8bb05c0ea470301f5d61e - SDWebImage: 46a7f73228f84ce80990c786e4372cf4db5875ce + SDWebImage: 5fcdb02cc35e05fc35791ec514b191d27189f872 SDWebImageSwiftUI: 1b67183dd2ef0321b2ccf578775de8e47eaceb77 SDWebImageWebPCoder: 947093edd1349d820c40afbd9f42acb6cdecd987 PODFILE CHECKSUM: 3fb06a5173225e197f3a4bf2be7e5586a693257a -COCOAPODS: 1.8.3 +COCOAPODS: 1.7.5 diff --git a/Example/SDWebImageSwiftUIDemo/ContentView.swift b/Example/SDWebImageSwiftUIDemo/ContentView.swift index 41fc69ad..331592f5 100644 --- a/Example/SDWebImageSwiftUIDemo/ContentView.swift +++ b/Example/SDWebImageSwiftUIDemo/ContentView.swift @@ -67,6 +67,9 @@ struct ContentView: View { Button(action: { self.reloadCache() }) { Text("Reload") } + Button(action: { self.switchView() }) { + Text("Switch") + } } #endif } diff --git a/Example/SDWebImageSwiftUIDemo/DetailView.swift b/Example/SDWebImageSwiftUIDemo/DetailView.swift index 02b82f80..ebcd3cee 100644 --- a/Example/SDWebImageSwiftUIDemo/DetailView.swift +++ b/Example/SDWebImageSwiftUIDemo/DetailView.swift @@ -33,7 +33,7 @@ struct DetailView: View { contentView() } #endif - #if os(macOS) + #if os(macOS) || os(watchOS) if animated { contentView() .contextMenu { @@ -45,16 +45,12 @@ struct DetailView: View { contentView() } #endif - #if os(watchOS) - contentView() - #endif Spacer() } } func contentView() -> some View { HStack { - #if os(iOS) || os(tvOS) || os(macOS) if animated { AnimatedImage(url: URL(string:url), options: [.progressiveLoad], isAnimating: $isAnimating) .onProgress(perform: { (receivedSize, expectedSize) in @@ -79,18 +75,6 @@ struct DetailView: View { .resizable() .scaledToFit() } - #else - WebImage(url: URL(string:url), options: [.progressiveLoad]) - .onProgress(perform: { (receivedSize, expectedSize) in - if (expectedSize >= 0) { - self.progress = CGFloat(receivedSize) / CGFloat(expectedSize) - } else { - self.progress = 1 - } - }) - .resizable() - .scaledToFit() - #endif } } } diff --git a/SDWebImageSwiftUI.xcodeproj/project.pbxproj b/SDWebImageSwiftUI.xcodeproj/project.pbxproj index 3ec68bb0..b40a111f 100644 --- a/SDWebImageSwiftUI.xcodeproj/project.pbxproj +++ b/SDWebImageSwiftUI.xcodeproj/project.pbxproj @@ -39,6 +39,14 @@ 32C43E3322FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */; }; 32C43E3422FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */; }; 32C43E3522FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */; }; + 32D9204E2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32D9204F2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32D920502349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32D920512349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32D920522349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */; }; + 32D920532349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */; }; + 32D920542349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */; }; + 32D920552349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -104,6 +112,8 @@ 32C43E2922FD586200BE87F5 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/tvOS/SDWebImage.framework; sourceTree = ""; }; 32C43E2D22FD586E00BE87F5 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/watchOS/SDWebImage.framework; sourceTree = ""; }; 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDWebImageSwiftUI.swift; sourceTree = ""; }; + 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDAnimatedImageInterface.h; sourceTree = ""; }; + 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDAnimatedImageInterface.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -180,6 +190,8 @@ 32C43DDF22FD54C600BE87F5 /* AnimatedImage.swift */, 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */, 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */, + 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */, + 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */, ); path = Classes; sourceTree = ""; @@ -202,6 +214,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 32D9204E2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */, 32C43DE622FD54CD00BE87F5 /* SDWebImageSwiftUI.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -210,6 +223,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 32D9204F2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */, 32C43E2222FD583A00BE87F5 /* SDWebImageSwiftUI.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -218,6 +232,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 32D920502349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */, 32C43E2322FD583B00BE87F5 /* SDWebImageSwiftUI.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -226,6 +241,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 32D920512349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */, 32C43E2422FD583C00BE87F5 /* SDWebImageSwiftUI.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -320,15 +336,19 @@ TargetAttributes = { 32C43DCB22FD540D00BE87F5 = { CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1100; }; 32C43DF322FD57FD00BE87F5 = { CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1100; }; 32C43E0022FD581400BE87F5 = { CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1100; }; 32C43E0D22FD581C00BE87F5 = { CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1100; }; }; }; @@ -394,6 +414,7 @@ 326E480A23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */, 32C43E1622FD583700BE87F5 /* ImageManager.swift in Sources */, 32C43E1822FD583700BE87F5 /* AnimatedImage.swift in Sources */, + 32D920522349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -406,6 +427,7 @@ 326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */, 32C43E1922FD583700BE87F5 /* ImageManager.swift in Sources */, 32C43E1B22FD583700BE87F5 /* AnimatedImage.swift in Sources */, + 32D920532349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -418,6 +440,7 @@ 326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */, 32C43E1C22FD583800BE87F5 /* ImageManager.swift in Sources */, 32C43E1E22FD583800BE87F5 /* AnimatedImage.swift in Sources */, + 32D920542349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -430,6 +453,7 @@ 326E480D23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */, 32C43E1F22FD583800BE87F5 /* ImageManager.swift in Sources */, 32C43E2122FD583800BE87F5 /* AnimatedImage.swift in Sources */, + 32D920552349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -565,6 +589,7 @@ 32C43DD522FD540D00BE87F5 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -585,6 +610,7 @@ PRODUCT_NAME = SDWebImageSwiftUI; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -593,6 +619,7 @@ 32C43DD622FD540D00BE87F5 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -621,6 +648,7 @@ 32C43DFA22FD57FD00BE87F5 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; @@ -643,6 +671,7 @@ PRODUCT_NAME = SDWebImageSwiftUI; SDKROOT = macosx; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; name = Debug; @@ -650,6 +679,7 @@ 32C43DFB22FD57FD00BE87F5 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; @@ -679,6 +709,7 @@ 32C43E0722FD581400BE87F5 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -699,6 +730,7 @@ PRODUCT_NAME = SDWebImageSwiftUI; SDKROOT = appletvos; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 3; }; @@ -707,6 +739,7 @@ 32C43E0822FD581400BE87F5 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -736,6 +769,7 @@ isa = XCBuildConfiguration; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -756,6 +790,7 @@ PRODUCT_NAME = SDWebImageSwiftUI; SDKROOT = watchos; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 4; }; @@ -765,6 +800,7 @@ isa = XCBuildConfiguration; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index e1fdda0a..e667661c 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -9,8 +9,6 @@ import SwiftUI import SDWebImage -#if !os(watchOS) - // Data Binding Object final class AnimatedImageModel : ObservableObject { @Published var image: PlatformImage? @@ -90,7 +88,7 @@ public struct AnimatedImage : PlatformViewRepresentable { /// - Parameter isAnimating: The binding for animation control public init(name: String, bundle: Bundle? = nil, isAnimating: Binding) { self._isAnimating = isAnimating - #if os(macOS) + #if os(macOS) || os(watchOS) let image = SDAnimatedImage(named: name, in: bundle) #else let image = SDAnimatedImage(named: name, in: bundle, compatibleWith: nil) @@ -117,8 +115,10 @@ public struct AnimatedImage : PlatformViewRepresentable { #if os(macOS) public typealias NSViewType = AnimatedImageViewWrapper - #else + #elseif os(iOS) || os(tvOS) public typealias UIViewType = AnimatedImageViewWrapper + #elseif os(watchOS) + public typealias WKInterfaceObjectType = SDAnimatedImageInterface #endif #if os(macOS) @@ -129,7 +129,7 @@ public struct AnimatedImage : PlatformViewRepresentable { public func updateNSView(_ nsView: AnimatedImageViewWrapper, context: NSViewRepresentableContext) { updateView(nsView, context: context) } - #else + #elseif os(iOS) || os(tvOS) public func makeUIView(context: UIViewRepresentableContext) -> AnimatedImageViewWrapper { makeView(context: context) } @@ -139,6 +139,26 @@ public struct AnimatedImage : PlatformViewRepresentable { } #endif + #if os(watchOS) + public func makeWKInterfaceObject(context: WKInterfaceObjectRepresentableContext) -> SDAnimatedImageInterface { + SDAnimatedImageInterface() + } + + public func updateWKInterfaceObject(_ view: SDAnimatedImageInterface, context: WKInterfaceObjectRepresentableContext) { + view.setImage(imageModel.image) + if let url = imageModel.url { + view.sd_setImage(with: url, completed: nil) + } + +// if self.isAnimating { +// view.startAnimating() +// } else { +// view.stopAnimating() +// } + } + #endif + + #if os(iOS) || os(tvOS) || os(macOS) func makeView(context: PlatformViewRepresentableContext) -> AnimatedImageViewWrapper { AnimatedImageViewWrapper() } @@ -304,6 +324,7 @@ public struct AnimatedImage : PlatformViewRepresentable { view.wrapped.shouldCustomLoopCount = false } } + #endif } // Layout @@ -463,5 +484,3 @@ struct AnimatedImage_Previews : PreviewProvider { } } #endif - -#endif diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h new file mode 100644 index 00000000..14aa58ae --- /dev/null +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h @@ -0,0 +1,19 @@ +// +// SDAnimatedImageInterface.h +// SDWebImageSwiftUI +// +// Created by lizhuoli on 2019/10/6. +// Copyright © 2019 SDWebImage. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SDAnimatedImageInterface : WKInterfaceImage + +- (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0); + +@end + +NS_ASSUME_NONNULL_END diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m new file mode 100644 index 00000000..a6492422 --- /dev/null +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m @@ -0,0 +1,198 @@ +// +// SDAnimatedImageInterface.m +// SDWebImageSwiftUI +// +// Created by lizhuoli on 2019/10/6. +// Copyright © 2019 SDWebImage. All rights reserved. +// + +#import "SDAnimatedImageInterface.h" +#import +#import + +@interface WKInterfaceObject () + +- (instancetype)_initForDynamicCreationWithInterfaceProperty:(NSString *)property; + +@end + +@interface SDAnimatedImageStatus : NSObject + +@property (nonatomic, assign) BOOL shouldAnimate; +@property (nonatomic, assign) CGImageAnimationStatus animationStatus; + +@end + +@implementation SDAnimatedImageStatus + +@end + +@interface SDAnimatedImageInterface () + +@property (nonatomic, strong, readwrite) UIImage *currentFrame; +@property (nonatomic, assign, readwrite) NSUInteger currentFrameIndex; +@property (nonatomic, assign, readwrite) NSUInteger currentLoopCount; +@property (nonatomic, assign) NSUInteger totalFrameCount; +@property (nonatomic, assign) NSUInteger totalLoopCount; +@property (nonatomic, strong) UIImage *animatedImage; +@property (nonatomic, assign) CGFloat animatedImageScale; +@property (nonatomic, strong) SDAnimatedImageStatus *currentStatus; + +@end + +@implementation SDAnimatedImageInterface + +- (instancetype)init { + Class cls = [self class]; + NSString *UUID = [NSUUID UUID].UUIDString; + NSString *property = [NSString stringWithFormat:@"%@_%@", cls, UUID]; + self = [self _initForDynamicCreationWithInterfaceProperty:property]; + return self; +} + +-(NSDictionary *)interfaceDescriptionForDynamicCreation { + return @{ + @"type" : @"image", + @"property" : self.interfaceProperty + }; +} + +- (void)setImage:(UIImage *)image { + // Stop animating + [self stopAnimating]; + // Reset all value + [self resetAnimatedImage]; + + [super setImage:image]; + if ([image.class conformsToProtocol:@protocol(SDAnimatedImage)]) { + UIImage *animatedImage = (UIImage *)image; + NSUInteger animatedImageFrameCount = animatedImage.animatedImageFrameCount; + // Check the frame count + if (animatedImageFrameCount <= 1) { + return; + } + self.animatedImage = animatedImage; + self.totalFrameCount = animatedImageFrameCount; + // Get the current frame and loop count. + self.totalLoopCount = self.animatedImage.animatedImageLoopCount; + // Get the scale + self.animatedImageScale = image.scale; + + NSData *animatedImageData = animatedImage.animatedImageData; + SDImageFormat format = [NSData sd_imageFormatForImageData:animatedImageData]; + if (format == SDImageFormatGIF || format == SDImageFormatPNG) { + [self startBuiltInAnimationWithImage:animatedImage]; + } + + // Update should animate + [self updateShouldAnimate]; + } +} + +- (void)startBuiltInAnimationWithImage:(UIImage *)animatedImage { + NSData *animatedImageData = animatedImage.animatedImageData; + NSUInteger maxLoopCount = 0; + if (maxLoopCount == 0) { + // The documentation says `kCFNumberPositiveInfinity may be used`, but it actually treat as 1 loop count + // 0 was treated as 1 loop count as well, not the same as Image/IO or UIKit + maxLoopCount = ((__bridge NSNumber *)kCFNumberPositiveInfinity).unsignedIntegerValue - 1; + } + NSDictionary *options = @{(__bridge NSString *)kCGImageAnimationLoopCount : @(maxLoopCount)}; + SDAnimatedImageStatus *status = [SDAnimatedImageStatus new]; + status.shouldAnimate = YES; + __weak typeof(self) wself = self; + status.animationStatus = CGAnimateImageDataWithBlock((__bridge CFDataRef)animatedImageData, (__bridge CFDictionaryRef)options, ^(size_t index, CGImageRef _Nonnull imageRef, bool * _Nonnull stop) { + __strong typeof(wself) self = wself; + if (!self) { + *stop = YES; + return; + } + if (!status.shouldAnimate) { + *stop = YES; + return; + } + // The CGImageRef provided by this API is GET only, should not call CGImageRelease + self.currentFrame = [[UIImage alloc] initWithCGImage:imageRef scale:self.animatedImageScale orientation:UIImageOrientationUp]; + self.currentFrameIndex = index; + [super setImage:self.currentFrame]; + }); + + self.currentStatus = status; +} + +- (void)resetAnimatedImage +{ + self.animatedImage = nil; + self.totalFrameCount = 0; + self.totalLoopCount = 0; + // reset current state + self.currentStatus.shouldAnimate = NO; + self.currentStatus = nil; + [self resetCurrentFrameIndex]; + self.animatedImageScale = 1; +} + +- (void)resetCurrentFrameIndex +{ + self.currentFrame = nil; + self.currentFrameIndex = 0; + self.currentLoopCount = 0; +} + +- (void)updateShouldAnimate +{ + self.currentStatus.shouldAnimate = self.animatedImage && self.totalFrameCount > 1; +} + +- (void)startAnimating { + if (self.animatedImage) { + self.currentStatus.shouldAnimate = YES; + } else { + [super startAnimating]; + } +} + +- (void)startAnimatingWithImagesInRange:(NSRange)imageRange duration:(NSTimeInterval)duration repeatCount:(NSInteger)repeatCount { + if (self.animatedImage) { + self.currentStatus.shouldAnimate = YES; + } else { + [super startAnimatingWithImagesInRange:imageRange duration:duration repeatCount:repeatCount]; + } +} + +- (void)stopAnimating { + if (self.animatedImage) { + self.currentStatus.shouldAnimate = YES; + } else { + [super stopAnimating]; + } +} + +- (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 diff --git a/SDWebImageSwiftUI/Module/SDWebImageSwiftUI.h b/SDWebImageSwiftUI/Module/SDWebImageSwiftUI.h index fa5a9c45..958fe3ec 100644 --- a/SDWebImageSwiftUI/Module/SDWebImageSwiftUI.h +++ b/SDWebImageSwiftUI/Module/SDWebImageSwiftUI.h @@ -7,6 +7,7 @@ */ #import +#import //! Project version number for SDWebImageSwiftUI. FOUNDATION_EXPORT double SDWebImageSwiftUIVersionNumber; From 80d251016a6de9dd2730493d4926ce481b483516 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sat, 12 Oct 2019 03:53:53 +0800 Subject: [PATCH 02/17] Update the hack for wacthKit experienment, fix the retain cycle issue that cause WKInterfaceImage not dealloc --- Example/Podfile.lock | 12 ++++---- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++ SDWebImageSwiftUI/Classes/AnimatedImage.swift | 10 +++---- .../Classes/SDAnimatedImageInterface.m | 28 +++++++++++++------ 4 files changed, 39 insertions(+), 19 deletions(-) create mode 100644 Example/SDWebImageSwiftUI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 1638bdb2..207726e9 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -8,9 +8,9 @@ PODS: - libwebp/mux (1.0.3): - libwebp/demux - libwebp/webp (1.0.3) - - SDWebImage (5.2.2): - - SDWebImage/Core (= 5.2.2) - - SDWebImage/Core (5.2.2) + - SDWebImage (5.2.3): + - SDWebImage/Core (= 5.2.3) + - SDWebImage/Core (5.2.3) - SDWebImageSwiftUI (0.3.1): - SDWebImage (~> 5.1) - SDWebImageWebPCoder (0.2.5): @@ -22,7 +22,7 @@ DEPENDENCIES: - SDWebImageWebPCoder SPEC REPOS: - https://github.com/cocoapods/specs.git: + trunk: - libwebp - SDWebImage - SDWebImageWebPCoder @@ -33,10 +33,10 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: libwebp: 057912d6d0abfb6357d8bb05c0ea470301f5d61e - SDWebImage: 5fcdb02cc35e05fc35791ec514b191d27189f872 + SDWebImage: 46a7f73228f84ce80990c786e4372cf4db5875ce SDWebImageSwiftUI: 1b67183dd2ef0321b2ccf578775de8e47eaceb77 SDWebImageWebPCoder: 947093edd1349d820c40afbd9f42acb6cdecd987 PODFILE CHECKSUM: 3fb06a5173225e197f3a4bf2be7e5586a693257a -COCOAPODS: 1.7.5 +COCOAPODS: 1.8.3 diff --git a/Example/SDWebImageSwiftUI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/SDWebImageSwiftUI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Example/SDWebImageSwiftUI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index e667661c..8a6df5b9 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -150,11 +150,11 @@ public struct AnimatedImage : PlatformViewRepresentable { view.sd_setImage(with: url, completed: nil) } -// if self.isAnimating { -// view.startAnimating() -// } else { -// view.stopAnimating() -// } + if self.isAnimating { + view.startAnimating() + } else { + view.stopAnimating() + } } #endif diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m index a6492422..aa75740f 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m @@ -10,6 +10,7 @@ #import #import +// This is needed for dynamic created WKInterfaceObject, like `WKInterfaceMap` @interface WKInterfaceObject () - (instancetype)_initForDynamicCreationWithInterfaceProperty:(NSString *)property; @@ -27,7 +28,9 @@ @implementation SDAnimatedImageStatus @end -@interface SDAnimatedImageInterface () +@interface SDAnimatedImageInterface () { + UIImage *_image; +} @property (nonatomic, strong, readwrite) UIImage *currentFrame; @property (nonatomic, assign, readwrite) NSUInteger currentFrameIndex; @@ -53,13 +56,17 @@ - (instancetype)init { -(NSDictionary *)interfaceDescriptionForDynamicCreation { return @{ @"type" : @"image", - @"property" : self.interfaceProperty + @"property" : self.interfaceProperty, + @"contentMode" : @(1), // UIViewContentModeScaleAspectFit }; } - (void)setImage:(UIImage *)image { - // Stop animating - [self stopAnimating]; + if (_image == image) { + return; + } + _image = image; + // Reset all value [self resetAnimatedImage]; @@ -114,12 +121,17 @@ - (void)startBuiltInAnimationWithImage:(UIImage *)animatedImage // The CGImageRef provided by this API is GET only, should not call CGImageRelease self.currentFrame = [[UIImage alloc] initWithCGImage:imageRef scale:self.animatedImageScale orientation:UIImageOrientationUp]; self.currentFrameIndex = index; - [super setImage:self.currentFrame]; + // Render the frame + [self display]; }); self.currentStatus = status; } +- (void)display { + [super setImage:self.currentFrame]; +} + - (void)resetAnimatedImage { self.animatedImage = nil; @@ -147,7 +159,7 @@ - (void)updateShouldAnimate - (void)startAnimating { if (self.animatedImage) { self.currentStatus.shouldAnimate = YES; - } else { + } else if (_image.images.count > 0) { [super startAnimating]; } } @@ -155,7 +167,7 @@ - (void)startAnimating { - (void)startAnimatingWithImagesInRange:(NSRange)imageRange duration:(NSTimeInterval)duration repeatCount:(NSInteger)repeatCount { if (self.animatedImage) { self.currentStatus.shouldAnimate = YES; - } else { + } else if (_image.images.count > 0) { [super startAnimatingWithImagesInRange:imageRange duration:duration repeatCount:repeatCount]; } } @@ -163,7 +175,7 @@ - (void)startAnimatingWithImagesInRange:(NSRange)imageRange duration:(NSTimeInte - (void)stopAnimating { if (self.animatedImage) { self.currentStatus.shouldAnimate = YES; - } else { + } else if (_image.images.count > 0) { [super stopAnimating]; } } From 9d5d5fd5e57206515f2f13a4c9e4e27dd600e510 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sat, 19 Oct 2019 21:09:07 +0800 Subject: [PATCH 03/17] Solve the merge conflict and try again --- Example/Podfile.lock | 6 +++--- Example/SDWebImageSwiftUIDemo/ContentView.swift | 7 ------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 207726e9..d9a8d3e8 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -11,7 +11,7 @@ PODS: - SDWebImage (5.2.3): - SDWebImage/Core (= 5.2.3) - SDWebImage/Core (5.2.3) - - SDWebImageSwiftUI (0.3.1): + - SDWebImageSwiftUI (0.3.2): - SDWebImage (~> 5.1) - SDWebImageWebPCoder (0.2.5): - libwebp (~> 1.0) @@ -34,9 +34,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: libwebp: 057912d6d0abfb6357d8bb05c0ea470301f5d61e SDWebImage: 46a7f73228f84ce80990c786e4372cf4db5875ce - SDWebImageSwiftUI: 1b67183dd2ef0321b2ccf578775de8e47eaceb77 + SDWebImageSwiftUI: a8a03ef596dde2e9668a76794f6c59d194289bb0 SDWebImageWebPCoder: 947093edd1349d820c40afbd9f42acb6cdecd987 PODFILE CHECKSUM: 3fb06a5173225e197f3a4bf2be7e5586a693257a -COCOAPODS: 1.8.3 +COCOAPODS: 1.8.4 diff --git a/Example/SDWebImageSwiftUIDemo/ContentView.swift b/Example/SDWebImageSwiftUIDemo/ContentView.swift index 331592f5..021ba49f 100644 --- a/Example/SDWebImageSwiftUIDemo/ContentView.swift +++ b/Example/SDWebImageSwiftUIDemo/ContentView.swift @@ -79,7 +79,6 @@ struct ContentView: View { ForEach(imageURLs) { url in NavigationLink(destination: DetailView(url: url, animated: self.animated)) { HStack { - #if os(iOS) || os(tvOS) || os(macOS) if self.animated { AnimatedImage(url: URL(string:url)) .resizable() @@ -91,12 +90,6 @@ struct ContentView: View { .scaledToFit() .frame(width: CGFloat(100), height: CGFloat(100), alignment: .center) } - #else - WebImage(url: URL(string:url)) - .resizable() - .scaledToFit() - .frame(width: CGFloat(100), height: CGFloat(100), alignment: .center) - #endif Text((url as NSString).lastPathComponent) } } From 33fb3d338af6c22403967242d6e9c8be68e82152 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sat, 19 Oct 2019 22:08:38 +0800 Subject: [PATCH 04/17] Add support for contentMode --- SDWebImageSwiftUI/Classes/AnimatedImage.swift | 17 +++++++++++ .../Classes/SDAnimatedImageInterface.h | 2 ++ .../Classes/SDAnimatedImageInterface.m | 30 ++++++++++++++----- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index 8a6df5b9..0652568f 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -155,6 +155,23 @@ public struct AnimatedImage : PlatformViewRepresentable { } else { view.stopAnimating() } + + layoutView(view, context: context) + } + + func layoutView(_ view: SDAnimatedImageInterface, context: PlatformViewRepresentableContext) { + // AspectRatio + if let _ = imageLayout.aspectRatio { + // TODO: Needs layer transform and geometry calculation + } + + // ContentMode + switch imageLayout.contentMode { + case .fit: + view.setContentMode(.aspectFit) + case .fill: + view.setContentMode(.fill) + } } #endif diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h index 14aa58ae..25e5945b 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h @@ -7,12 +7,14 @@ // #import +#import NS_ASSUME_NONNULL_BEGIN @interface SDAnimatedImageInterface : WKInterfaceImage - (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0); +- (void)setContentMode:(SDImageScaleMode)contentMode; @end diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m index aa75740f..9c775480 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m @@ -10,10 +10,21 @@ #import #import -// This is needed for dynamic created WKInterfaceObject, like `WKInterfaceMap` +@protocol CALayerProtocol +@property (nullable, strong) id contents; +@end + +@protocol UIViewProtocol +@property (nonatomic, strong, readonly) id layer; +@property (nonatomic, assign) SDImageScaleMode contentMode; +@end + @interface WKInterfaceObject () +// This is needed for dynamic created WKInterfaceObject, like `WKInterfaceMap` - (instancetype)_initForDynamicCreationWithInterfaceProperty:(NSString *)property; +// This is remote UIView +@property (nonatomic, strong, readonly) id _interfaceView; @end @@ -46,7 +57,7 @@ @interface SDAnimatedImageInterface () { @implementation SDAnimatedImageInterface - (instancetype)init { - Class cls = [self class]; + Class cls = [super class]; NSString *UUID = [NSUUID UUID].UUIDString; NSString *property = [NSString stringWithFormat:@"%@_%@", cls, UUID]; self = [self _initForDynamicCreationWithInterfaceProperty:property]; @@ -56,8 +67,7 @@ - (instancetype)init { -(NSDictionary *)interfaceDescriptionForDynamicCreation { return @{ @"type" : @"image", - @"property" : self.interfaceProperty, - @"contentMode" : @(1), // UIViewContentModeScaleAspectFit + @"property" : self.interfaceProperty }; } @@ -122,14 +132,16 @@ - (void)startBuiltInAnimationWithImage:(UIImage *)animatedImage self.currentFrame = [[UIImage alloc] initWithCGImage:imageRef scale:self.animatedImageScale orientation:UIImageOrientationUp]; self.currentFrameIndex = index; // Render the frame - [self display]; + [self displayLayer]; }); self.currentStatus = status; } -- (void)display { - [super setImage:self.currentFrame]; +- (void)displayLayer { + if (self.currentFrame) { + [self _interfaceView].layer.contents = (__bridge id)self.currentFrame.CGImage; + } } - (void)resetAnimatedImage @@ -180,6 +192,10 @@ - (void)stopAnimating { } } +- (void)setContentMode:(SDImageScaleMode)contentMode { + [self _interfaceView].contentMode = contentMode; +} + - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options From 7f94bf691b866216ebe1515f4a8595a693c1fada Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sat, 19 Oct 2019 22:31:21 +0800 Subject: [PATCH 05/17] Fix the SDAnimatedImageInterface first appear shows empty issues --- SDWebImageSwiftUI/Classes/AnimatedImage.swift | 10 ++++- .../Classes/SDAnimatedImageInterface.h | 14 +++---- .../Classes/SDAnimatedImageInterface.m | 37 ++++++++++++++----- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index 0652568f..ce376241 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -147,7 +147,15 @@ public struct AnimatedImage : PlatformViewRepresentable { public func updateWKInterfaceObject(_ view: SDAnimatedImageInterface, context: WKInterfaceObjectRepresentableContext) { view.setImage(imageModel.image) if let url = imageModel.url { - view.sd_setImage(with: url, completed: nil) + view.sd_setImage(with: url, placeholderImage: placeholder, options: webOptions, context: webContext, progress: { (receivedSize, expectedSize, _) in + self.imageModel.progressBlock?(receivedSize, expectedSize) + }) { (image, error, cacheType, _) in + if let image = image { + self.imageModel.successBlock?(image, cacheType) + } else { + self.imageModel.failureBlock?(error ?? NSError()) + } + } } if self.isAnimating { diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h index 25e5945b..7af4e982 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h @@ -1,10 +1,10 @@ -// -// SDAnimatedImageInterface.h -// SDWebImageSwiftUI -// -// Created by lizhuoli on 2019/10/6. -// Copyright © 2019 SDWebImage. All rights reserved. -// +/* +* This file is part of the SDWebImage package. +* (c) DreamPiggy +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ #import #import diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m index 9c775480..120ffb4a 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m @@ -1,10 +1,10 @@ -// -// SDAnimatedImageInterface.m -// SDWebImageSwiftUI -// -// Created by lizhuoli on 2019/10/6. -// Copyright © 2019 SDWebImage. All rights reserved. -// +/* +* This file is part of the SDWebImage package. +* (c) DreamPiggy +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ #import "SDAnimatedImageInterface.h" #import @@ -57,17 +57,36 @@ @interface SDAnimatedImageInterface () { @implementation SDAnimatedImageInterface - (instancetype)init { - Class cls = [super class]; + Class cls = [self class]; NSString *UUID = [NSUUID UUID].UUIDString; NSString *property = [NSString stringWithFormat:@"%@_%@", cls, UUID]; self = [self _initForDynamicCreationWithInterfaceProperty:property]; return self; } ++ (UIImage *)sharedEmptyImage { + // This is used for placeholder on `WKInterfaceImage` + // Do not using `[UIImage new]` because WatchKit will ignore it + static dispatch_once_t onceToken; + static UIImage *image; + dispatch_once(&onceToken, ^{ + UIColor *color = UIColor.clearColor; + CGRect rect = CGRectMake(0, 0, 1, 1); + UIGraphicsBeginImageContext(rect.size); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(context, [color CGColor]); + CGContextFillRect(context, rect); + image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + }); + return image; +} + -(NSDictionary *)interfaceDescriptionForDynamicCreation { return @{ @"type" : @"image", - @"property" : self.interfaceProperty + @"property" : self.interfaceProperty, + @"image" : [self.class sharedEmptyImage] }; } From cf588c881c85aec5febbf7551f6207c3f0686be8 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sat, 19 Oct 2019 22:51:50 +0800 Subject: [PATCH 06/17] Fix the scale factor support for SDAniamtedImageInterface --- SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m index 120ffb4a..c445472b 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m @@ -12,6 +12,7 @@ @protocol CALayerProtocol @property (nullable, strong) id contents; +@property CGFloat contentsScale; @end @protocol UIViewProtocol @@ -159,7 +160,9 @@ - (void)startBuiltInAnimationWithImage:(UIImage *)animatedImage - (void)displayLayer { if (self.currentFrame) { - [self _interfaceView].layer.contents = (__bridge id)self.currentFrame.CGImage; + id layer = [self _interfaceView].layer; + layer.contentsScale = self.animatedImageScale; + layer.contents = (__bridge id)self.currentFrame.CGImage; } } From 473682132a981075e6b7970df7eaa7874c359f02 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sat, 19 Oct 2019 23:15:51 +0800 Subject: [PATCH 07/17] Fix the compile issue on other platforms --- .../Classes/SDAnimatedImageInterface.h | 8 +-- .../Classes/SDAnimatedImageInterface.m | 49 ++++++++++++------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h index 7af4e982..02abc3d8 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h @@ -6,16 +6,12 @@ * file that was distributed with this source code. */ -#import #import - -NS_ASSUME_NONNULL_BEGIN - +#if SD_WATCH @interface SDAnimatedImageInterface : WKInterfaceImage - (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0); - (void)setContentMode:(SDImageScaleMode)contentMode; @end - -NS_ASSUME_NONNULL_END +#endif diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m index c445472b..64cfcbfb 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m @@ -7,9 +7,12 @@ */ #import "SDAnimatedImageInterface.h" +#if SD_WATCH #import #import +#pragma mark - SPI + @protocol CALayerProtocol @property (nullable, strong) id contents; @property CGFloat contentsScale; @@ -65,6 +68,15 @@ - (instancetype)init { return self; } +- (NSDictionary *)interfaceDescriptionForDynamicCreation { + // This is called by WatchKit + return @{ + @"type" : @"image", + @"property" : self.interfaceProperty, + @"image" : [self.class sharedEmptyImage] + }; +} + + (UIImage *)sharedEmptyImage { // This is used for placeholder on `WKInterfaceImage` // Do not using `[UIImage new]` because WatchKit will ignore it @@ -83,14 +95,6 @@ + (UIImage *)sharedEmptyImage { return image; } --(NSDictionary *)interfaceDescriptionForDynamicCreation { - return @{ - @"type" : @"image", - @"property" : self.interfaceProperty, - @"image" : [self.class sharedEmptyImage] - }; -} - - (void)setImage:(UIImage *)image { if (_image == image) { return; @@ -218,12 +222,22 @@ - (void)setContentMode:(SDImageScaleMode)contentMode { [self _interfaceView].contentMode = contentMode; } +@end + +#pragma mark - Web Cache + +@interface SDAnimatedImageInterface (WebCache) + +@end + +@implementation SDAnimatedImageInterface (WebCache) + - (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 { + 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) { @@ -239,10 +253,11 @@ - (void)sd_setImageWithURL:(nullable NSURL *)url 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); - } - }]; + if (completedBlock) { + completedBlock(image, error, cacheType, imageURL); + } + }]; } @end +#endif From ab7a54cfa778f46a8b5c3a2aebb57c1b59b08264 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sun, 20 Oct 2019 16:51:55 +0800 Subject: [PATCH 08/17] Stop animtiong when dismantle for watchOS AnimatedImage --- SDWebImageSwiftUI/Classes/AnimatedImage.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index 02d8a527..408df051 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -175,6 +175,10 @@ public struct AnimatedImage : PlatformViewRepresentable { layoutView(view, context: context) } + public static func dismantleWKInterfaceObject(_ view: SDAnimatedImageInterface, coordinator: ()) { + view.stopAnimating() + } + func layoutView(_ view: SDAnimatedImageInterface, context: PlatformViewRepresentableContext) { // AspectRatio if let _ = imageLayout.aspectRatio { From dfb9ab4a8484bbfb140bad1fe7d10d78488e1230 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Mon, 21 Oct 2019 21:29:20 +0800 Subject: [PATCH 09/17] Fix the issue that stopAnimating does not stop :) --- SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m index 64cfcbfb..a5f68666 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m @@ -212,7 +212,7 @@ - (void)startAnimatingWithImagesInRange:(NSRange)imageRange duration:(NSTimeInte - (void)stopAnimating { if (self.animatedImage) { - self.currentStatus.shouldAnimate = YES; + self.currentStatus.shouldAnimate = NO; } else if (_image.images.count > 0) { [super stopAnimating]; } From f1af6c26bf476ee8043ad4d48101f4885cc4842d Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Mon, 21 Oct 2019 21:32:29 +0800 Subject: [PATCH 10/17] Fix the warning because of Apple's bug --- SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m index a5f68666..2269402b 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m @@ -9,7 +9,11 @@ #import "SDAnimatedImageInterface.h" #if SD_WATCH #import +// ImageIO.modulemap does not contains this public header +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wincomplete-umbrella" #import +#pragma clang diagnostic pop #pragma mark - SPI From bdbf0a511b66bdf011e39035e188e3768c79cee4 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Mon, 21 Oct 2019 22:21:07 +0800 Subject: [PATCH 11/17] Use macro to integrate the watchOS Animation solution --- SDWebImageSwiftUI/Classes/AnimatedImage.swift | 88 ++++++++----------- .../Classes/SDAnimatedImageInterface.h | 4 + 2 files changed, 43 insertions(+), 49 deletions(-) diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index 408df051..0de86fc4 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -36,6 +36,16 @@ final class AnimatedImageConfiguration: ObservableObject { @Published var customLoopCount: Int? } +// Convenient +#if os(watchOS) +public typealias AnimatedImageViewWrapper = SDAnimatedImageInterface +extension SDAnimatedImageInterface { + var wrapped: SDAnimatedImageInterface { + return self + } +} +#endif + // View public struct AnimatedImage : PlatformViewRepresentable { @ObservedObject var imageModel = AnimatedImageModel() @@ -118,7 +128,7 @@ public struct AnimatedImage : PlatformViewRepresentable { #elseif os(iOS) || os(tvOS) public typealias UIViewType = AnimatedImageViewWrapper #elseif os(watchOS) - public typealias WKInterfaceObjectType = SDAnimatedImageInterface + public typealias WKInterfaceObjectType = AnimatedImageViewWrapper #endif #if os(macOS) @@ -145,63 +155,30 @@ public struct AnimatedImage : PlatformViewRepresentable { public static func dismantleUIView(_ uiView: AnimatedImageViewWrapper, coordinator: ()) { dismantleView(uiView, coordinator: coordinator) } - #endif - - #if os(watchOS) - public func makeWKInterfaceObject(context: WKInterfaceObjectRepresentableContext) -> SDAnimatedImageInterface { - SDAnimatedImageInterface() - } - - public func updateWKInterfaceObject(_ view: SDAnimatedImageInterface, context: WKInterfaceObjectRepresentableContext) { - view.setImage(imageModel.image) - if let url = imageModel.url { - view.sd_setImage(with: url, placeholderImage: placeholder, options: webOptions, context: webContext, progress: { (receivedSize, expectedSize, _) in - self.imageModel.progressBlock?(receivedSize, expectedSize) - }) { (image, error, cacheType, _) in - if let image = image { - self.imageModel.successBlock?(image, cacheType) - } else { - self.imageModel.failureBlock?(error ?? NSError()) - } - } - } - - if self.isAnimating { - view.startAnimating() - } else { - view.stopAnimating() - } - - layoutView(view, context: context) + #elseif os(watchOS) + public func makeWKInterfaceObject(context: WKInterfaceObjectRepresentableContext) -> AnimatedImageViewWrapper { + makeView(context: context) } - public static func dismantleWKInterfaceObject(_ view: SDAnimatedImageInterface, coordinator: ()) { - view.stopAnimating() + public func updateWKInterfaceObject(_ wkInterfaceObject: AnimatedImageViewWrapper, context: WKInterfaceObjectRepresentableContext) { + updateView(wkInterfaceObject, context: context) } - func layoutView(_ view: SDAnimatedImageInterface, context: PlatformViewRepresentableContext) { - // AspectRatio - if let _ = imageLayout.aspectRatio { - // TODO: Needs layer transform and geometry calculation - } - - // ContentMode - switch imageLayout.contentMode { - case .fit: - view.setContentMode(.aspectFit) - case .fill: - view.setContentMode(.fill) - } + public static func dismantleWKInterfaceObject(_ wkInterfaceObject: AnimatedImageViewWrapper, coordinator: ()) { + dismantleView(wkInterfaceObject, coordinator: coordinator) } #endif - #if os(iOS) || os(tvOS) || os(macOS) func makeView(context: PlatformViewRepresentableContext) -> AnimatedImageViewWrapper { AnimatedImageViewWrapper() } func updateView(_ view: AnimatedImageViewWrapper, context: PlatformViewRepresentableContext) { + #if os(watchOS) + view.wrapped.setImage(imageModel.image) + #else view.wrapped.image = imageModel.image + #endif if let url = imageModel.url { view.wrapped.sd_setImage(with: url, placeholderImage: placeholder, options: webOptions, context: webContext, progress: { (receivedSize, expectedSize, _) in self.imageModel.progressBlock?(receivedSize, expectedSize) @@ -218,7 +195,7 @@ public struct AnimatedImage : PlatformViewRepresentable { if self.isAnimating != view.wrapped.animates { view.wrapped.animates = self.isAnimating } - #else + #elseif os(iOS) || os(tvOS) if self.isAnimating != view.wrapped.isAnimating { if self.isAnimating { view.wrapped.startAnimating() @@ -226,6 +203,12 @@ public struct AnimatedImage : PlatformViewRepresentable { view.wrapped.stopAnimating() } } + #elseif os(watchOS) + if self.isAnimating { + view.wrapped.startAnimating() + } else { + view.wrapped.stopAnimating() + } #endif configureView(view, context: context) @@ -251,17 +234,22 @@ public struct AnimatedImage : PlatformViewRepresentable { case .fit: #if os(macOS) view.wrapped.imageScaling = .scaleProportionallyUpOrDown - #else + #elseif os(iOS) || os(tvOS) view.wrapped.contentMode = .scaleAspectFit + #else + view.wrapped.setContentMode(.aspectFit) #endif case .fill: #if os(macOS) view.wrapped.imageScaling = .scaleAxesIndependently - #else + #elseif os(iOS) || os(tvOS) view.wrapped.contentMode = .scaleToFill + #else + view.wrapped.setContentMode(.fill) #endif } + #if os(macOS) || os(iOS) || os(tvOS) // Animated Image does not support resizing mode and rendering mode if let image = view.wrapped.image, !image.sd_isAnimated, !image.conforms(to: SDAnimatedImageProtocol.self) { // ResizingMode @@ -344,9 +332,11 @@ public struct AnimatedImage : PlatformViewRepresentable { view.setNeedsLayout() view.setNeedsDisplay() #endif + #endif } func configureView(_ view: AnimatedImageViewWrapper, context: PlatformViewRepresentableContext) { + #if os(macOS) || os(iOS) || os(tvOS) // IncrementalLoad if let incrementalLoad = imageConfiguration.incrementalLoad { view.wrapped.shouldIncrementalLoad = incrementalLoad @@ -368,8 +358,8 @@ public struct AnimatedImage : PlatformViewRepresentable { // disable custom loop count view.wrapped.shouldCustomLoopCount = false } + #endif } - #endif } // Layout diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h index 02abc3d8..348848cf 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h @@ -8,10 +8,14 @@ #import #if SD_WATCH +NS_ASSUME_NONNULL_BEGIN + @interface SDAnimatedImageInterface : WKInterfaceImage - (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0); - (void)setContentMode:(SDImageScaleMode)contentMode; @end + +NS_ASSUME_NONNULL_END #endif From a9fa3539a58792b707944b93e13b58d5b95d5eb3 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Mon, 21 Oct 2019 22:44:58 +0800 Subject: [PATCH 12/17] Refactory code to fix that calling sd_setImage(with:) multiple times issues --- SDWebImageSwiftUI/Classes/AnimatedImage.swift | 71 +++++++++++++------ 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index 0de86fc4..5df4c4ad 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -12,7 +12,6 @@ import SDWebImage // Data Binding Object final class AnimatedImageModel : ObservableObject { @Published var image: PlatformImage? - @Published var url: URL? @Published var successBlock: ((PlatformImage, SDImageCacheType) -> Void)? @Published var failureBlock: ((Error) -> Void)? @Published var progressBlock: ((Int, Int) -> Void)? @@ -52,6 +51,7 @@ public struct AnimatedImage : PlatformViewRepresentable { @ObservedObject var imageLayout = AnimatedImageLayout() @ObservedObject var imageConfiguration = AnimatedImageConfiguration() + var url: URL? var placeholder: PlatformImage? var webOptions: SDWebImageOptions = [] var webContext: [SDWebImageContextOption : Any]? = nil @@ -80,7 +80,7 @@ public struct AnimatedImage : PlatformViewRepresentable { self.placeholder = placeholder self.webOptions = options self.webContext = context - self.imageModel.url = url + self.url = url } /// Create an animated image with name and bundle. @@ -174,19 +174,23 @@ public struct AnimatedImage : PlatformViewRepresentable { } func updateView(_ view: AnimatedImageViewWrapper, context: PlatformViewRepresentableContext) { - #if os(watchOS) - view.wrapped.setImage(imageModel.image) - #else - view.wrapped.image = imageModel.image - #endif - if let url = imageModel.url { - view.wrapped.sd_setImage(with: url, placeholderImage: placeholder, options: webOptions, context: webContext, progress: { (receivedSize, expectedSize, _) in - self.imageModel.progressBlock?(receivedSize, expectedSize) - }) { (image, error, cacheType, _) in - if let image = image { - self.imageModel.successBlock?(image, cacheType) - } else { - self.imageModel.failureBlock?(error ?? NSError()) + if let image = imageModel.image { + #if os(watchOS) + view.wrapped.setImage(image) + #else + view.wrapped.image = image + #endif + } else { + if let url = url { + view.wrapped.sd_setImage(with: url, placeholderImage: placeholder, options: webOptions, context: webContext, progress: { (receivedSize, expectedSize, _) in + self.imageModel.progressBlock?(receivedSize, expectedSize) + }) { (image, error, cacheType, _) in + self.imageModel.image = image + if let image = image { + self.imageModel.successBlock?(image, cacheType) + } else { + self.imageModel.failureBlock?(error ?? NSError()) + } } } } @@ -236,7 +240,7 @@ public struct AnimatedImage : PlatformViewRepresentable { view.wrapped.imageScaling = .scaleProportionallyUpOrDown #elseif os(iOS) || os(tvOS) view.wrapped.contentMode = .scaleAspectFit - #else + #elseif os(watchOS) view.wrapped.setContentMode(.aspectFit) #endif case .fill: @@ -244,14 +248,14 @@ public struct AnimatedImage : PlatformViewRepresentable { view.wrapped.imageScaling = .scaleAxesIndependently #elseif os(iOS) || os(tvOS) view.wrapped.contentMode = .scaleToFill - #else + #elseif os(watchOS) view.wrapped.setContentMode(.fill) #endif } - #if os(macOS) || os(iOS) || os(tvOS) // Animated Image does not support resizing mode and rendering mode - if let image = view.wrapped.image, !image.sd_isAnimated, !image.conforms(to: SDAnimatedImageProtocol.self) { + if let image = imageModel.image, !image.sd_isAnimated, !image.conforms(to: SDAnimatedImageProtocol.self) { + var image = image // ResizingMode if let resizingMode = imageLayout.resizingMode { #if os(macOS) @@ -265,14 +269,24 @@ public struct AnimatedImage : PlatformViewRepresentable { view.wrapped.image?.resizingMode = .stretch view.wrapped.image?.capInsets = capInsets #else - view.wrapped.image = view.wrapped.image?.resizableImage(withCapInsets: capInsets, resizingMode: .stretch) + image = image.resizableImage(withCapInsets: capInsets, resizingMode: .stretch) + #if os(iOS) || os(tvOS) + view.wrapped.image = image + #elseif os(watchOS) + view.wrapped.setImage(image) + #endif #endif case .tile: #if os(macOS) view.wrapped.image?.resizingMode = .tile view.wrapped.image?.capInsets = capInsets #else - view.wrapped.image = view.wrapped.image?.resizableImage(withCapInsets: capInsets, resizingMode: .tile) + image = image.resizableImage(withCapInsets: capInsets, resizingMode: .tile) + #if os(iOS) || os(tvOS) + view.wrapped.image = image + #elseif os(watchOS) + view.wrapped.setImage(image) + #endif #endif @unknown default: // Future cases, not implements @@ -287,13 +301,23 @@ public struct AnimatedImage : PlatformViewRepresentable { #if os(macOS) view.wrapped.image?.isTemplate = true #else - view.wrapped.image = view.wrapped.image?.withRenderingMode(.alwaysTemplate) + image = image.withRenderingMode(.alwaysTemplate) + #if os(iOS) || os(tvOS) + view.wrapped.image = image + #elseif os(watchOS) + view.wrapped.setImage(image) + #endif #endif case .original: #if os(macOS) view.wrapped.image?.isTemplate = false #else - view.wrapped.image = view.wrapped.image?.withRenderingMode(.alwaysOriginal) + image = image.withRenderingMode(.alwaysOriginal) + #if os(iOS) || os(tvOS) + view.wrapped.image = image + #elseif os(watchOS) + view.wrapped.setImage(image) + #endif #endif @unknown default: // Future cases, not implements @@ -302,6 +326,7 @@ public struct AnimatedImage : PlatformViewRepresentable { } } + #if os(macOS) || os(iOS) || os(tvOS) // Interpolation if let interpolation = imageLayout.interpolation { switch interpolation { From e456b38494badab424763c5141ce2ac560daeda0 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Mon, 21 Oct 2019 23:06:15 +0800 Subject: [PATCH 13/17] Support to custom loop count on watchOS AnimatedImage --- SDWebImageSwiftUI/Classes/AnimatedImage.swift | 7 +++++++ SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h | 1 + SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m | 8 +++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index 5df4c4ad..ed97e3e5 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -383,6 +383,13 @@ public struct AnimatedImage : PlatformViewRepresentable { // disable custom loop count view.wrapped.shouldCustomLoopCount = false } + #elseif os(watchOS) + if let customLoopCount = imageConfiguration.customLoopCount { + view.wrapped.setAnimationRepeatCount(customLoopCount as NSNumber) + } else { + // disable custom loop count + view.wrapped.setAnimationRepeatCount(nil) + } #endif } } diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h index 348848cf..c63e5f7d 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0); - (void)setContentMode:(SDImageScaleMode)contentMode; +- (void)setAnimationRepeatCount:(nullable NSNumber *)repeatCount; @end diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m index 2269402b..8f377550 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m @@ -59,6 +59,7 @@ @interface SDAnimatedImageInterface () { @property (nonatomic, strong) UIImage *animatedImage; @property (nonatomic, assign) CGFloat animatedImageScale; @property (nonatomic, strong) SDAnimatedImageStatus *currentStatus; +@property (nonatomic, strong) NSNumber *animationRepeatCount; @end @@ -136,7 +137,12 @@ - (void)setImage:(UIImage *)image { - (void)startBuiltInAnimationWithImage:(UIImage *)animatedImage { NSData *animatedImageData = animatedImage.animatedImageData; - NSUInteger maxLoopCount = 0; + NSUInteger maxLoopCount; + if (self.animationRepeatCount != nil) { + maxLoopCount = self.animationRepeatCount.unsignedIntegerValue; + } else { + maxLoopCount = animatedImage.animatedImageLoopCount; + } if (maxLoopCount == 0) { // The documentation says `kCFNumberPositiveInfinity may be used`, but it actually treat as 1 loop count // 0 was treated as 1 loop count as well, not the same as Image/IO or UIKit From 95bfc40320e37affa4c6a175855ba1436b955d07 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Mon, 21 Oct 2019 23:06:37 +0800 Subject: [PATCH 14/17] Fix the CocoaPods issues which does not have umbrella headers --- Example/Podfile.lock | 4 ++-- SDWebImageSwiftUI.podspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Example/Podfile.lock b/Example/Podfile.lock index d9a8d3e8..1f1ba4f2 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -11,7 +11,7 @@ PODS: - SDWebImage (5.2.3): - SDWebImage/Core (= 5.2.3) - SDWebImage/Core (5.2.3) - - SDWebImageSwiftUI (0.3.2): + - SDWebImageSwiftUI (0.3.3): - SDWebImage (~> 5.1) - SDWebImageWebPCoder (0.2.5): - libwebp (~> 1.0) @@ -34,7 +34,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: libwebp: 057912d6d0abfb6357d8bb05c0ea470301f5d61e SDWebImage: 46a7f73228f84ce80990c786e4372cf4db5875ce - SDWebImageSwiftUI: a8a03ef596dde2e9668a76794f6c59d194289bb0 + SDWebImageSwiftUI: 2284857313ca5085ab7b5310d372420d23c0817f SDWebImageWebPCoder: 947093edd1349d820c40afbd9f42acb6cdecd987 PODFILE CHECKSUM: 3fb06a5173225e197f3a4bf2be7e5586a693257a diff --git a/SDWebImageSwiftUI.podspec b/SDWebImageSwiftUI.podspec index 8ec2d2e2..c9b9c373 100644 --- a/SDWebImageSwiftUI.podspec +++ b/SDWebImageSwiftUI.podspec @@ -26,7 +26,7 @@ Which aims to provide a better support for SwiftUI users. s.tvos.deployment_target = '13.0' s.watchos.deployment_target = '6.0' - s.source_files = 'SDWebImageSwiftUI/Classes/**/*' + s.source_files = 'SDWebImageSwiftUI/Classes/**/*', 'SDWebImageSwiftUI/Module/*.h' s.frameworks = 'SwiftUI' s.dependency 'SDWebImage', '~> 5.1' From 73a9ff0fd84b6b4f2bf0e931ce26db83429f7275 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Mon, 21 Oct 2019 23:12:21 +0800 Subject: [PATCH 15/17] Update some of the documentations --- SDWebImageSwiftUI/Classes/AnimatedImage.swift | 9 ++++++--- SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index ed97e3e5..20830c0b 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -489,9 +489,11 @@ extension AnimatedImage { } /// Provide a max buffer size by bytes. This is used to adjust frame buffer count and can be useful when the decoding cost is expensive (such as Animated WebP software decoding). Default is nil. - // `0` or nil means automatically adjust by calculating current memory usage. - // `1` means without any buffer cache, each of frames will be decoded and then be freed after rendering. (Lowest Memory and Highest CPU) - // `UInt.max` means cache all the buffer. (Lowest CPU and Highest Memory) + /// + /// `0` or nil means automatically adjust by calculating current memory usage. + /// `1` means without any buffer cache, each of frames will be decoded and then be freed after rendering. (Lowest Memory and Highest CPU) + /// `UInt.max` means cache all the buffer. (Lowest CPU and Highest Memory) + /// - Warning: watchOS does not implementes. /// - Parameter bufferSize: The max buffer size public func maxBufferSize(_ bufferSize: UInt?) -> AnimatedImage { imageConfiguration.maxBufferSize = bufferSize @@ -501,6 +503,7 @@ extension AnimatedImage { /// Whehter or not to enable incremental image load for animated image. See `SDAnimatedImageView` for detailed explanation for this. /// - Note: If you are confused about this description, open Chrome browser to view some large GIF images with low network speed to see the animation behavior. /// Default is true. Set to false to only render the static poster for incremental animated image. + /// - Warning: watchOS does not implementes. /// - Parameter incrementalLoad: Whether or not to incremental load public func incrementalLoad(_ incrementalLoad: Bool) -> AnimatedImage { imageConfiguration.incrementalLoad = incrementalLoad diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h index c63e5f7d..a07d788d 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h +++ b/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h @@ -10,6 +10,7 @@ #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. @interface SDAnimatedImageInterface : WKInterfaceImage - (instancetype)init WK_AVAILABLE_WATCHOS_ONLY(6.0); From 30bc73f718035ea2eeb5acda1c968d396b43c273 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Mon, 21 Oct 2019 23:40:26 +0800 Subject: [PATCH 16/17] Try to solve the SwiftPM issue because it does not support mixed Objective-C and Swift code, really suck, Apple :) --- Package.swift | 12 ++++- SDWebImageSwiftUI.xcodeproj/project.pbxproj | 48 +++++++++++-------- SDWebImageSwiftUI/Classes/AnimatedImage.swift | 3 ++ .../{ => ObjC}/SDAnimatedImageInterface.h | 3 +- .../{ => ObjC}/SDAnimatedImageInterface.m | 1 - 5 files changed, 44 insertions(+), 23 deletions(-) rename SDWebImageSwiftUI/Classes/{ => ObjC}/SDAnimatedImageInterface.h (95%) rename SDWebImageSwiftUI/Classes/{ => ObjC}/SDAnimatedImageInterface.m (99%) diff --git a/Package.swift b/Package.swift index 9c5c3885..7de10e4f 100644 --- a/Package.swift +++ b/Package.swift @@ -24,7 +24,17 @@ 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"], + 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"), + path: "SDWebImageSwiftUI/Classes/ObjC", + sources: ["SDAnimatedImageInterface.h", "SDAnimatedImageInterface.m"], + publicHeadersPath: "." + ) ] ) diff --git a/SDWebImageSwiftUI.xcodeproj/project.pbxproj b/SDWebImageSwiftUI.xcodeproj/project.pbxproj index b40a111f..b539c52c 100644 --- a/SDWebImageSwiftUI.xcodeproj/project.pbxproj +++ b/SDWebImageSwiftUI.xcodeproj/project.pbxproj @@ -7,6 +7,14 @@ 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 */; }; 326E480A23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; }; 326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; }; 326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; }; @@ -39,14 +47,6 @@ 32C43E3322FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */; }; 32C43E3422FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */; }; 32C43E3522FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */; }; - 32D9204E2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32D9204F2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32D920502349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32D920512349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32D920522349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */; }; - 32D920532349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */; }; - 32D920542349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */; }; - 32D920552349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -97,6 +97,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDAnimatedImageInterface.h; sourceTree = ""; }; + 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDAnimatedImageInterface.m; sourceTree = ""; }; 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewWrapper.swift; sourceTree = ""; }; 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 = ""; }; @@ -112,8 +114,6 @@ 32C43E2922FD586200BE87F5 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/tvOS/SDWebImage.framework; sourceTree = ""; }; 32C43E2D22FD586E00BE87F5 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/watchOS/SDWebImage.framework; sourceTree = ""; }; 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDWebImageSwiftUI.swift; sourceTree = ""; }; - 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDAnimatedImageInterface.h; sourceTree = ""; }; - 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDAnimatedImageInterface.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -152,6 +152,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 324F61C4235E07EC003973B8 /* ObjC */ = { + isa = PBXGroup; + children = ( + 324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */, + 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */, + ); + path = ObjC; + sourceTree = ""; + }; 32C43DC222FD540D00BE87F5 = { isa = PBXGroup; children = ( @@ -185,13 +194,12 @@ 32C43DDB22FD54C600BE87F5 /* Classes */ = { isa = PBXGroup; children = ( + 324F61C4235E07EC003973B8 /* ObjC */, 32C43DDC22FD54C600BE87F5 /* ImageManager.swift */, 32C43DDE22FD54C600BE87F5 /* WebImage.swift */, 32C43DDF22FD54C600BE87F5 /* AnimatedImage.swift */, 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */, 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */, - 32D9204C2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h */, - 32D9204D2349DBFC00C9CBE9 /* SDAnimatedImageInterface.m */, ); path = Classes; sourceTree = ""; @@ -214,7 +222,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 32D9204E2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */, + 324F61C7235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */, 32C43DE622FD54CD00BE87F5 /* SDWebImageSwiftUI.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -223,7 +231,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 32D9204F2349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */, + 324F61C8235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */, 32C43E2222FD583A00BE87F5 /* SDWebImageSwiftUI.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -232,7 +240,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 32D920502349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */, + 324F61C9235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */, 32C43E2322FD583B00BE87F5 /* SDWebImageSwiftUI.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -241,7 +249,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 32D920512349DBFC00C9CBE9 /* SDAnimatedImageInterface.h in Headers */, + 324F61CA235E07EC003973B8 /* SDAnimatedImageInterface.h in Headers */, 32C43E2422FD583C00BE87F5 /* SDWebImageSwiftUI.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -414,7 +422,7 @@ 326E480A23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */, 32C43E1622FD583700BE87F5 /* ImageManager.swift in Sources */, 32C43E1822FD583700BE87F5 /* AnimatedImage.swift in Sources */, - 32D920522349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */, + 324F61CB235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -427,7 +435,7 @@ 326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */, 32C43E1922FD583700BE87F5 /* ImageManager.swift in Sources */, 32C43E1B22FD583700BE87F5 /* AnimatedImage.swift in Sources */, - 32D920532349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */, + 324F61CC235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -440,7 +448,7 @@ 326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */, 32C43E1C22FD583800BE87F5 /* ImageManager.swift in Sources */, 32C43E1E22FD583800BE87F5 /* AnimatedImage.swift in Sources */, - 32D920542349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */, + 324F61CD235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -453,7 +461,7 @@ 326E480D23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */, 32C43E1F22FD583800BE87F5 /* ImageManager.swift in Sources */, 32C43E2122FD583800BE87F5 /* AnimatedImage.swift in Sources */, - 32D920552349DBFC00C9CBE9 /* SDAnimatedImageInterface.m in Sources */, + 324F61CE235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index 20830c0b..da63db90 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -8,6 +8,9 @@ import SwiftUI import SDWebImage +#if canImport(SDWebImageSwiftUIObjC) +import SDWebImageSwiftUIObjC +#endif // Data Binding Object final class AnimatedImageModel : ObservableObject { diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h b/SDWebImageSwiftUI/Classes/ObjC/SDAnimatedImageInterface.h similarity index 95% rename from SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h rename to SDWebImageSwiftUI/Classes/ObjC/SDAnimatedImageInterface.h index a07d788d..08e0b7a9 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.h +++ b/SDWebImageSwiftUI/Classes/ObjC/SDAnimatedImageInterface.h @@ -6,7 +6,8 @@ * file that was distributed with this source code. */ -#import +@import SDWebImage; + #if SD_WATCH NS_ASSUME_NONNULL_BEGIN diff --git a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m b/SDWebImageSwiftUI/Classes/ObjC/SDAnimatedImageInterface.m similarity index 99% rename from SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m rename to SDWebImageSwiftUI/Classes/ObjC/SDAnimatedImageInterface.m index 8f377550..2fabf582 100644 --- a/SDWebImageSwiftUI/Classes/SDAnimatedImageInterface.m +++ b/SDWebImageSwiftUI/Classes/ObjC/SDAnimatedImageInterface.m @@ -8,7 +8,6 @@ #import "SDAnimatedImageInterface.h" #if SD_WATCH -#import // ImageIO.modulemap does not contains this public header #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wincomplete-umbrella" From 2e9af2fcb09050a279913ffa58636b8a212d3507 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Tue, 22 Oct 2019 00:03:20 +0800 Subject: [PATCH 17/17] Fix travis CI script to only build Carthage. Swift cli build can not works on Objective-C code import syntax, but works on Xcode --- .travis.yml | 3 ++- Cartfile.resolved | 2 +- Package.swift | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 659b32a9..d987e2e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,4 +33,5 @@ script: - pod install --project-directory=Example - xcodebuild build -workspace Example/SDWebImageSwiftUI.xcworkspace -scheme SDWebImageSwiftUIDemo -sdk iphonesimulator -destination 'name=iPhone 8' ONLY_ACTIVE_ARCH=NO | xcpretty -c - - swift build \ No newline at end of file + - carthage update --platform iOS + - xcodebuild build -project SDWebImageSwiftUI.xcodeproj -scheme 'SDWebImageSwiftUI' -sdk iphonesimulator -configuration Debug | xcpretty -c \ No newline at end of file diff --git a/Cartfile.resolved b/Cartfile.resolved index 98fdac58..b3575d5a 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "SDWebImage/SDWebImage" "5.1.0" +github "SDWebImage/SDWebImage" "5.2.3" diff --git a/Package.swift b/Package.swift index 7de10e4f..1acb937b 100644 --- a/Package.swift +++ b/Package.swift @@ -33,7 +33,6 @@ let package = Package( name: "SDWebImageSwiftUIObjC", dependencies: ["SDWebImage"], path: "SDWebImageSwiftUI/Classes/ObjC", - sources: ["SDAnimatedImageInterface.h", "SDAnimatedImageInterface.m"], publicHeadersPath: "." ) ]