Change the API of completionHandler for ImageManager, without return value. Add test cases
This commit is contained in:
parent
80bc832504
commit
72c7c8d693
|
@ -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",
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue