Skip to content

[Important changes]Trying to move the initial state setup before onAppear to fix the watchOS switching url or any other state issue #316

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions SDWebImageSwiftUI.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@
objects = {

/* Begin PBXBuildFile section */
3243AFE62AA37EFF0049A43B /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B79C9428DB40430088C432 /* SwiftUICompatibility.swift */; };
3243AFE72AA37EFF0049A43B /* WebImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43DDE22FD54C600BE87F5 /* WebImage.swift */; };
3243AFE82AA37EFF0049A43B /* ImagePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */; };
3243AFE92AA37EFF0049A43B /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
@@ -26,10 +25,6 @@
326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
326E480D23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
329885EE2AA37FCB0071F2BA /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 329885ED2AA37FCB0071F2BA /* SDWebImage.framework */; };
32B79C9528DB40430088C432 /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B79C9428DB40430088C432 /* SwiftUICompatibility.swift */; };
32B79C9628DB40430088C432 /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B79C9428DB40430088C432 /* SwiftUICompatibility.swift */; };
32B79C9728DB40430088C432 /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B79C9428DB40430088C432 /* SwiftUICompatibility.swift */; };
32B79C9828DB40430088C432 /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B79C9428DB40430088C432 /* SwiftUICompatibility.swift */; };
32B933E523659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
32B933E623659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
32B933E723659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
@@ -83,7 +78,6 @@
326B84812363350C0011BDFB /* Indicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Indicator.swift; sourceTree = "<group>"; };
326E480923431C0F00C633E9 /* ImageViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewWrapper.swift; sourceTree = "<group>"; };
329885ED2AA37FCB0071F2BA /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/visionOS/SDWebImage.framework; sourceTree = "<group>"; };
32B79C9428DB40430088C432 /* SwiftUICompatibility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftUICompatibility.swift; sourceTree = "<group>"; };
32B933E423659A1900BB7CAD /* Transition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transition.swift; sourceTree = "<group>"; };
32C43DCC22FD540D00BE87F5 /* SDWebImageSwiftUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSwiftUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageManager.swift; sourceTree = "<group>"; };
@@ -221,7 +215,6 @@
32C43DDE22FD54C600BE87F5 /* WebImage.swift */,
32C43DDF22FD54C600BE87F5 /* AnimatedImage.swift */,
32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */,
32B79C9428DB40430088C432 /* SwiftUICompatibility.swift */,
326E480923431C0F00C633E9 /* ImageViewWrapper.swift */,
32D26A012446B546005905DA /* Image.swift */,
);
@@ -491,7 +484,6 @@
3243AFEB2AA37EFF0049A43B /* AnimatedImage.swift in Sources */,
3243AFE82AA37EFF0049A43B /* ImagePlayer.swift in Sources */,
3243AFED2AA37EFF0049A43B /* SDWebImageSwiftUI.swift in Sources */,
3243AFE62AA37EFF0049A43B /* SwiftUICompatibility.swift in Sources */,
3243AFEE2AA37F010049A43B /* Indicator.swift in Sources */,
3243AFEA2AA37EFF0049A43B /* Image.swift in Sources */,
);
@@ -507,7 +499,6 @@
326B84822363350C0011BDFB /* Indicator.swift in Sources */,
32C43E3222FD5DE100BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
326E480A23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
32B79C9528DB40430088C432 /* SwiftUICompatibility.swift in Sources */,
32C43E1622FD583700BE87F5 /* ImageManager.swift in Sources */,
32C43E1822FD583700BE87F5 /* AnimatedImage.swift in Sources */,
32D26A022446B546005905DA /* Image.swift in Sources */,
@@ -524,7 +515,6 @@
326B84832363350C0011BDFB /* Indicator.swift in Sources */,
32C43E3322FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
32B79C9628DB40430088C432 /* SwiftUICompatibility.swift in Sources */,
32C43E1922FD583700BE87F5 /* ImageManager.swift in Sources */,
32C43E1B22FD583700BE87F5 /* AnimatedImage.swift in Sources */,
32D26A032446B546005905DA /* Image.swift in Sources */,
@@ -541,7 +531,6 @@
326B84842363350C0011BDFB /* Indicator.swift in Sources */,
32C43E3422FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
32B79C9728DB40430088C432 /* SwiftUICompatibility.swift in Sources */,
32C43E1C22FD583800BE87F5 /* ImageManager.swift in Sources */,
32C43E1E22FD583800BE87F5 /* AnimatedImage.swift in Sources */,
32D26A042446B546005905DA /* Image.swift in Sources */,
@@ -558,7 +547,6 @@
326B84852363350C0011BDFB /* Indicator.swift in Sources */,
32C43E3522FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
326E480D23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
32B79C9828DB40430088C432 /* SwiftUICompatibility.swift in Sources */,
32C43E1F22FD583800BE87F5 /* ImageManager.swift in Sources */,
32C43E2122FD583800BE87F5 /* AnimatedImage.swift in Sources */,
32D26A052446B546005905DA /* Image.swift in Sources */,
50 changes: 39 additions & 11 deletions SDWebImageSwiftUI/Classes/ImageManager.swift
Original file line number Diff line number Diff line change
@@ -15,17 +15,47 @@ import SDWebImage
@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *)
public final class ImageManager : ObservableObject {
/// loaded image, note when progressive loading, this will published multiple times with different partial image
@Published public var image: PlatformImage?
public var image: PlatformImage? {
didSet {
DispatchQueue.main.async {
self.objectWillChange.send()
}
}
}
/// loaded image data, may be nil if hit from memory cache. This will only published once even on incremental image loading
@Published public var imageData: Data?
public var imageData: Data? {
didSet {
DispatchQueue.main.async {
self.objectWillChange.send()
}
}
}
/// loaded image cache type, .none means from network
@Published public var cacheType: SDImageCacheType = .none
public var cacheType: SDImageCacheType = .none {
didSet {
DispatchQueue.main.async {
self.objectWillChange.send()
}
}
}
/// 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?
public var error: Error? {
didSet {
DispatchQueue.main.async {
self.objectWillChange.send()
}
}
}
/// true means during incremental loading
@Published public var isIncremental: Bool = false
public var isIncremental: Bool = false {
didSet {
DispatchQueue.main.async {
self.objectWillChange.send()
}
}
}
/// A observed object to pass through the image manager loading status to indicator
@Published public var indicatorStatus = IndicatorStatus()
public var indicatorStatus = IndicatorStatus()

weak var currentOperation: SDWebImageOperation? = nil

@@ -51,8 +81,8 @@ public final class ImageManager : ObservableObject {
return
}
currentURL = url
indicatorStatus.isLoading = true
indicatorStatus.progress = 0
self.indicatorStatus.isLoading = true
self.indicatorStatus.progress = 0
currentOperation = manager.loadImage(with: url, options: options, context: context, progress: { [weak self] (receivedSize, expectedSize, _) in
guard let self = self else {
return
@@ -63,9 +93,7 @@ public final class ImageManager : ObservableObject {
} else {
progress = 0
}
DispatchQueue.main.async {
self.indicatorStatus.progress = progress
}
self.indicatorStatus.progress = progress
self.progressBlock?(receivedSize, expectedSize)
}) { [weak self] (image, data, error, cacheType, finished, _) in
guard let self = self else {
16 changes: 14 additions & 2 deletions SDWebImageSwiftUI/Classes/Indicator/Indicator.swift
Original file line number Diff line number Diff line change
@@ -28,9 +28,21 @@ public struct Indicator<T> where T : View {
@available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *)
public class IndicatorStatus : ObservableObject {
/// whether indicator is loading or not
@Published var isLoading: Bool = false
var isLoading: Bool = false {
didSet {
DispatchQueue.main.async {
self.objectWillChange.send()
}
}
}
/// indicator progress, should only be used for indicator binding, value between [0.0, 1.0]
@Published var progress: Double = 0
var progress: Double = 0 {
didSet {
DispatchQueue.main.async {
self.objectWillChange.send()
}
}
}
}

/// A implementation detail View Modifier with indicator
92 changes: 0 additions & 92 deletions SDWebImageSwiftUI/Classes/SwiftUICompatibility.swift

This file was deleted.

24 changes: 15 additions & 9 deletions SDWebImageSwiftUI/Classes/WebImage.swift
Original file line number Diff line number Diff line change
@@ -163,26 +163,22 @@ public struct WebImage<Content> : View where Content: View {
}
} else {
content((imageManager.error != nil) ? .failure(imageManager.error!) : .empty)
setupPlaceholder()
setupInitialState()
// Load Logic
.onPlatformAppear(appear: {
self.setupManager()
if (self.imageManager.error == nil) {
// Load remote image when first appear
self.imageManager.load(url: imageModel.url, options: imageModel.options, context: imageModel.context)
}
.onAppear {
guard self.imageConfiguration.retryOnAppear else { return }
// When using prorgessive loading, the new partial image will cause onAppear. Filter this case
if self.imageManager.error != nil && !self.imageManager.isIncremental {
self.imageManager.load(url: imageModel.url, options: imageModel.options, context: imageModel.context)
}
}, disappear: {
}
.onDisappear {
guard self.imageConfiguration.cancelOnDisappear else { return }
// When using prorgessive loading, the previous partial image will cause onDisappear. Filter this case
if self.imageManager.error != nil && !self.imageManager.isIncremental {
self.imageManager.cancel()
}
})
}
}
}
}
@@ -328,6 +324,16 @@ public struct WebImage<Content> : View where Content: View {
}
}

/// Initial state management (update when imageModel.url changed)
func setupInitialState() -> some View {
self.setupManager()
if (self.imageManager.error == nil) {
// Load remote image when first appear
self.imageManager.load(url: imageModel.url, options: imageModel.options, context: imageModel.context)
}
return setupPlaceholder()
}

/// Placeholder View Support
func setupPlaceholder() -> some View {
let result = content((imageManager.error != nil) ? .failure(imageManager.error!) : .empty)