Change the API of completionHandler for ImageManager, without return value. Add test cases

This commit is contained in:
DreamPiggy 2020-03-24 18:47:35 +08:00
parent 80bc832504
commit 72c7c8d693
5 changed files with 59 additions and 11 deletions

View File

@ -54,7 +54,7 @@ struct ContentView: View {
"https://www.sample-videos.com/img/Sample-png-image-1mb.png", "https://www.sample-videos.com/img/Sample-png-image-1mb.png",
"https://nr-platform.s3.amazonaws.com/uploads/platform/published_extension/branding_icon/275/AmazonS3.png", "https://nr-platform.s3.amazonaws.com/uploads/platform/published_extension/branding_icon/275/AmazonS3.png",
"https://raw.githubusercontent.com/ibireme/YYImage/master/Demo/YYImageDemo/mew_baseline.jpg", "https://raw.githubusercontent.com/ibireme/YYImage/master/Demo/YYImageDemo/mew_baseline.jpg",
"http://via.placeholder.com/200x200.jpg", "https://via.placeholder.com/200x200.jpg",
"https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/w3c.svg", "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/w3c.svg",
"https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/wikimedia.svg", "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/wikimedia.svg",
"https://raw.githubusercontent.com/icons8/flat-color-icons/master/pdf/stack_of_photos.pdf", "https://raw.githubusercontent.com/icons8/flat-color-icons/master/pdf/stack_of_photos.pdf",

View File

@ -79,6 +79,9 @@
32C43E3322FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */; }; 32C43E3322FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */; };
32C43E3422FD5DF400BE87F5 /* 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 */; }; 32C43E3522FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */; };
32ED4826242A13030053338E /* ImageManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32ED4825242A13030053338E /* ImageManagerTests.swift */; };
32ED4827242A13030053338E /* ImageManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32ED4825242A13030053338E /* ImageManagerTests.swift */; };
32ED4828242A13030053338E /* ImageManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32ED4825242A13030053338E /* ImageManagerTests.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -181,6 +184,7 @@
32C43E2922FD586200BE87F5 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/tvOS/SDWebImage.framework; sourceTree = "<group>"; }; 32C43E2922FD586200BE87F5 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/tvOS/SDWebImage.framework; sourceTree = "<group>"; };
32C43E2D22FD586E00BE87F5 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/watchOS/SDWebImage.framework; sourceTree = "<group>"; }; 32C43E2D22FD586E00BE87F5 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/watchOS/SDWebImage.framework; sourceTree = "<group>"; };
32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDWebImageSwiftUI.swift; sourceTree = "<group>"; }; 32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDWebImageSwiftUI.swift; sourceTree = "<group>"; };
32ED4825242A13030053338E /* ImageManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageManagerTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -257,6 +261,7 @@
3211F84623DE984D00FC757F /* AnimatedImageTests.swift */, 3211F84623DE984D00FC757F /* AnimatedImageTests.swift */,
3211F84F23DE98E300FC757F /* WebImageTests.swift */, 3211F84F23DE98E300FC757F /* WebImageTests.swift */,
32BD9C4623E03B08008D5F6A /* IndicatorTests.swift */, 32BD9C4623E03B08008D5F6A /* IndicatorTests.swift */,
32ED4825242A13030053338E /* ImageManagerTests.swift */,
322E0F4723E57F09006836DC /* TestUtils.swift */, 322E0F4723E57F09006836DC /* TestUtils.swift */,
); );
path = Tests; path = Tests;
@ -707,6 +712,7 @@
32BD9C4723E03B08008D5F6A /* IndicatorTests.swift in Sources */, 32BD9C4723E03B08008D5F6A /* IndicatorTests.swift in Sources */,
3211F84723DE984D00FC757F /* AnimatedImageTests.swift in Sources */, 3211F84723DE984D00FC757F /* AnimatedImageTests.swift in Sources */,
322E0F4823E57F09006836DC /* TestUtils.swift in Sources */, 322E0F4823E57F09006836DC /* TestUtils.swift in Sources */,
32ED4826242A13030053338E /* ImageManagerTests.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -718,6 +724,7 @@
32BD9C4823E03B08008D5F6A /* IndicatorTests.swift in Sources */, 32BD9C4823E03B08008D5F6A /* IndicatorTests.swift in Sources */,
321C1D6A23DEDB98009CF62A /* AnimatedImageTests.swift in Sources */, 321C1D6A23DEDB98009CF62A /* AnimatedImageTests.swift in Sources */,
322E0F4923E57F09006836DC /* TestUtils.swift in Sources */, 322E0F4923E57F09006836DC /* TestUtils.swift in Sources */,
32ED4827242A13030053338E /* ImageManagerTests.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -729,6 +736,7 @@
32BD9C4923E03B08008D5F6A /* IndicatorTests.swift in Sources */, 32BD9C4923E03B08008D5F6A /* IndicatorTests.swift in Sources */,
321C1D6C23DEDB98009CF62A /* AnimatedImageTests.swift in Sources */, 321C1D6C23DEDB98009CF62A /* AnimatedImageTests.swift in Sources */,
322E0F4A23E57F09006836DC /* TestUtils.swift in Sources */, 322E0F4A23E57F09006836DC /* TestUtils.swift in Sources */,
32ED4828242A13030053338E /* ImageManagerTests.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -15,6 +15,8 @@ import SDWebImage
public final class ImageManager : ObservableObject { public final class ImageManager : ObservableObject {
/// loaded image, note when progressive loading, this will published multiple times with different partial image /// loaded image, note when progressive loading, this will published multiple times with different partial image
@Published public var image: PlatformImage? @Published public var image: PlatformImage?
/// loading error, you can grab the error code and reason listed in `SDWebImageErrorDomain`, to provide a user interface about the error reason
@Published public var error: Error?
/// whether network is loading or cache is querying, should only be used for indicator binding /// whether network is loading or cache is querying, should only be used for indicator binding
@Published public var isLoading: Bool = false @Published public var isLoading: Bool = false
/// network progress, should only be used for indicator binding /// network progress, should only be used for indicator binding
@ -81,6 +83,7 @@ public final class ImageManager : ObservableObject {
return return
} }
self.image = image self.image = image
self.error = error
self.isIncremental = !finished self.isIncremental = !finished
if finished { if finished {
self.isLoading = false self.isLoading = false
@ -110,28 +113,22 @@ extension ImageManager {
/// Provide the action when image load fails. /// Provide the action when image load fails.
/// - Parameters: /// - Parameters:
/// - action: The action to perform. The first arg is the error during loading. If `action` is `nil`, the call has no effect. /// - action: The action to perform. The first arg is the error during loading. If `action` is `nil`, the call has no effect.
/// - Returns: A view that triggers `action` when this image load fails. public func setOnFailure(perform action: ((Error) -> Void)? = nil) {
public func onFailure(perform action: ((Error) -> Void)? = nil) -> ImageManager {
self.failureBlock = action self.failureBlock = action
return self
} }
/// Provide the action when image load successes. /// Provide the action when image load successes.
/// - Parameters: /// - Parameters:
/// - action: The action to perform. The first arg is the loaded image, the second arg is the cache type loaded from. If `action` is `nil`, the call has no effect. /// - action: The action to perform. The first arg is the loaded image, the second arg is the cache type loaded from. If `action` is `nil`, the call has no effect.
/// - Returns: A view that triggers `action` when this image load successes. public func setOnSuccess(perform action: ((PlatformImage, SDImageCacheType) -> Void)? = nil) {
public func onSuccess(perform action: ((PlatformImage, SDImageCacheType) -> Void)? = nil) -> ImageManager {
self.successBlock = action self.successBlock = action
return self
} }
/// Provide the action when image load progress changes. /// Provide the action when image load progress changes.
/// - Parameters: /// - Parameters:
/// - action: The action to perform. The first arg is the received size, the second arg is the total size, all in bytes. If `action` is `nil`, the call has no effect. /// - action: The action to perform. The first arg is the received size, the second arg is the total size, all in bytes. If `action` is `nil`, the call has no effect.
/// - Returns: A view that triggers `action` when this image load successes. public func setOnProgress(perform action: ((Int, Int) -> Void)? = nil) {
public func onProgress(perform action: ((Int, Int) -> Void)? = nil) -> ImageManager {
self.progressBlock = action self.progressBlock = action
return self
} }
} }

View File

@ -0,0 +1,43 @@
import XCTest
import SwiftUI
import ViewInspector
@testable import SDWebImageSwiftUI
class ImageManagerTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testImageManager() throws {
let expectation = self.expectation(description: "ImageManager usage with Combine")
let imageUrl = URL(string: "https://via.placeholder.com/500x500.jpg")
let imageManager = ImageManager(url: imageUrl)
imageManager.setOnSuccess { image, cacheType in
XCTAssertNotNil(image)
expectation.fulfill()
}
imageManager.setOnFailure { error in
XCTFail()
}
imageManager.setOnProgress { receivedSize, expectedSize in
}
imageManager.load()
XCTAssertNotNil(imageManager.currentOperation)
let sub = imageManager.objectWillChange
.subscribe(on: RunLoop.main)
.receive(on: RunLoop.main)
.sink { value in
print(value)
}
sub.cancel()
self.waitForExpectations(timeout: 5, handler: nil)
}
}

View File

@ -3,7 +3,7 @@ import SwiftUI
import ViewInspector import ViewInspector
@testable import SDWebImageSwiftUI @testable import SDWebImageSwiftUI
public extension PlatformViewRepresentable where Self: Inspectable { extension PlatformViewRepresentable where Self: Inspectable {
func platformView() throws -> PlatformViewType { func platformView() throws -> PlatformViewType {
#if os(macOS) #if os(macOS)