Fix the issue sometime the `WebImage` appear/disappear logic wrong. Using UIKit/AppKit to detect the visibility
This commit is contained in:
parent
5832951dd9
commit
b512e31d28
|
@ -75,6 +75,14 @@
|
||||||
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 */; };
|
||||||
|
32CBA78025E4D7D800C6A8DC /* ImagePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */; };
|
||||||
|
32CBA78125E4D7D800C6A8DC /* ImagePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */; };
|
||||||
|
32CBA78225E4D7D800C6A8DC /* ImagePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */; };
|
||||||
|
32CBA78325E4D7D800C6A8DC /* ImagePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */; };
|
||||||
|
32CBA78425E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */; };
|
||||||
|
32CBA78525E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */; };
|
||||||
|
32CBA78625E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */; };
|
||||||
|
32CBA78725E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */; };
|
||||||
32D26A022446B546005905DA /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D26A012446B546005905DA /* Image.swift */; };
|
32D26A022446B546005905DA /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D26A012446B546005905DA /* Image.swift */; };
|
||||||
32D26A032446B546005905DA /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D26A012446B546005905DA /* Image.swift */; };
|
32D26A032446B546005905DA /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D26A012446B546005905DA /* Image.swift */; };
|
||||||
32D26A042446B546005905DA /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D26A012446B546005905DA /* Image.swift */; };
|
32D26A042446B546005905DA /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D26A012446B546005905DA /* Image.swift */; };
|
||||||
|
@ -137,6 +145,8 @@
|
||||||
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>"; };
|
||||||
|
32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImagePlayer.swift; sourceTree = "<group>"; };
|
||||||
|
32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftUICompatibility.swift; sourceTree = "<group>"; };
|
||||||
32D26A012446B546005905DA /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
|
32D26A012446B546005905DA /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
|
||||||
32ED4825242A13030053338E /* ImageManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageManagerTests.swift; sourceTree = "<group>"; };
|
32ED4825242A13030053338E /* ImageManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageManagerTests.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
@ -279,6 +289,8 @@
|
||||||
32B933E323659A0700BB7CAD /* Transition */,
|
32B933E323659A0700BB7CAD /* Transition */,
|
||||||
326099472362E09E006EBB22 /* Indicator */,
|
326099472362E09E006EBB22 /* Indicator */,
|
||||||
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */,
|
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */,
|
||||||
|
32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */,
|
||||||
|
32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */,
|
||||||
32C43DDE22FD54C600BE87F5 /* WebImage.swift */,
|
32C43DDE22FD54C600BE87F5 /* WebImage.swift */,
|
||||||
32C43DDF22FD54C600BE87F5 /* AnimatedImage.swift */,
|
32C43DDF22FD54C600BE87F5 /* AnimatedImage.swift */,
|
||||||
32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */,
|
32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */,
|
||||||
|
@ -696,6 +708,8 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
32B933E523659A1900BB7CAD /* Transition.swift in Sources */,
|
32B933E523659A1900BB7CAD /* Transition.swift in Sources */,
|
||||||
|
32CBA78025E4D7D800C6A8DC /* ImagePlayer.swift in Sources */,
|
||||||
|
32CBA78425E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */,
|
||||||
32C43E1722FD583700BE87F5 /* WebImage.swift in Sources */,
|
32C43E1722FD583700BE87F5 /* WebImage.swift in Sources */,
|
||||||
326B848C236335400011BDFB /* ProgressIndicator.swift in Sources */,
|
326B848C236335400011BDFB /* ProgressIndicator.swift in Sources */,
|
||||||
326B84822363350C0011BDFB /* Indicator.swift in Sources */,
|
326B84822363350C0011BDFB /* Indicator.swift in Sources */,
|
||||||
|
@ -713,6 +727,8 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
32B933E623659A1900BB7CAD /* Transition.swift in Sources */,
|
32B933E623659A1900BB7CAD /* Transition.swift in Sources */,
|
||||||
|
32CBA78125E4D7D800C6A8DC /* ImagePlayer.swift in Sources */,
|
||||||
|
32CBA78525E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */,
|
||||||
32C43E1A22FD583700BE87F5 /* WebImage.swift in Sources */,
|
32C43E1A22FD583700BE87F5 /* WebImage.swift in Sources */,
|
||||||
326B848D236335400011BDFB /* ProgressIndicator.swift in Sources */,
|
326B848D236335400011BDFB /* ProgressIndicator.swift in Sources */,
|
||||||
326B84832363350C0011BDFB /* Indicator.swift in Sources */,
|
326B84832363350C0011BDFB /* Indicator.swift in Sources */,
|
||||||
|
@ -730,6 +746,8 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
32B933E723659A1900BB7CAD /* Transition.swift in Sources */,
|
32B933E723659A1900BB7CAD /* Transition.swift in Sources */,
|
||||||
|
32CBA78225E4D7D800C6A8DC /* ImagePlayer.swift in Sources */,
|
||||||
|
32CBA78625E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */,
|
||||||
32C43E1D22FD583800BE87F5 /* WebImage.swift in Sources */,
|
32C43E1D22FD583800BE87F5 /* WebImage.swift in Sources */,
|
||||||
326B848E236335400011BDFB /* ProgressIndicator.swift in Sources */,
|
326B848E236335400011BDFB /* ProgressIndicator.swift in Sources */,
|
||||||
326B84842363350C0011BDFB /* Indicator.swift in Sources */,
|
326B84842363350C0011BDFB /* Indicator.swift in Sources */,
|
||||||
|
@ -747,6 +765,8 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
32B933E823659A1900BB7CAD /* Transition.swift in Sources */,
|
32B933E823659A1900BB7CAD /* Transition.swift in Sources */,
|
||||||
|
32CBA78325E4D7D800C6A8DC /* ImagePlayer.swift in Sources */,
|
||||||
|
32CBA78725E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */,
|
||||||
32C43E2022FD583800BE87F5 /* WebImage.swift in Sources */,
|
32C43E2022FD583800BE87F5 /* WebImage.swift in Sources */,
|
||||||
326B848F236335400011BDFB /* ProgressIndicator.swift in Sources */,
|
326B848F236335400011BDFB /* ProgressIndicator.swift in Sources */,
|
||||||
326B84852363350C0011BDFB /* Indicator.swift in Sources */,
|
326B84852363350C0011BDFB /* Indicator.swift in Sources */,
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the SDWebImage package.
|
||||||
|
* (c) DreamPiggy <lizhuoli1126@126.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
#if os(iOS) || os(tvOS) || os(macOS)
|
||||||
|
|
||||||
|
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
|
||||||
|
struct PlatformAppear: PlatformViewRepresentable {
|
||||||
|
let appearAction: () -> Void
|
||||||
|
let disappearAction: () -> Void
|
||||||
|
|
||||||
|
#if os(iOS) || os(tvOS)
|
||||||
|
func makeUIView(context: Context) -> some UIView {
|
||||||
|
let view = PlatformAppearView()
|
||||||
|
view.appearAction = appearAction
|
||||||
|
view.disappearAction = disappearAction
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIView(_ uiView: UIViewType, context: Context) {}
|
||||||
|
#endif
|
||||||
|
#if os(macOS)
|
||||||
|
func makeNSView(context: Context) -> some NSView {
|
||||||
|
let view = PlatformAppearView()
|
||||||
|
view.appearAction = appearAction
|
||||||
|
view.disappearAction = disappearAction
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateNSView(_ nsView: NSViewType, context: Context) {}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
|
||||||
|
class PlatformAppearView: PlatformView {
|
||||||
|
var appearAction: () -> Void = {}
|
||||||
|
var disappearAction: () -> Void = {}
|
||||||
|
|
||||||
|
#if os(iOS) || os(tvOS)
|
||||||
|
override func willMove(toWindow newWindow: UIWindow?) {
|
||||||
|
if newWindow != nil {
|
||||||
|
appearAction()
|
||||||
|
} else {
|
||||||
|
disappearAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
override func viewWillMove(toWindow newWindow: NSWindow?) {
|
||||||
|
if newWindow != nil {
|
||||||
|
appearAction()
|
||||||
|
} else {
|
||||||
|
disappearAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extension View {
|
||||||
|
/// Used UIKit/AppKit behavior to detect the SwiftUI view's visibility.
|
||||||
|
/// This hack is because of SwiftUI 1.0/2.0 buggy behavior. The built-in `onAppear` and `onDisappear` is so massive on some cases. Where UIKit/AppKit is solid.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - appear: The action when view appears
|
||||||
|
/// - disappear: The action when view disappears
|
||||||
|
/// - Returns: Some view
|
||||||
|
func onPlatformAppear(appear: @escaping () -> Void = {}, disappear: @escaping () -> Void = {}) -> some View {
|
||||||
|
#if os(iOS) || os(tvOS) || os(macOS)
|
||||||
|
return self.background(PlatformAppear(appearAction: appear, disappearAction: disappear))
|
||||||
|
#else
|
||||||
|
return self.onAppear(perform: appear).onDisappear(perform: disappear)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,23 +65,22 @@ public struct WebImage : View {
|
||||||
if isAnimating && !imageManager.isIncremental {
|
if isAnimating && !imageManager.isIncremental {
|
||||||
if imagePlayer.currentFrame != nil {
|
if imagePlayer.currentFrame != nil {
|
||||||
configure(image: imagePlayer.currentFrame!)
|
configure(image: imagePlayer.currentFrame!)
|
||||||
.onAppear {
|
.onPlatformAppear(appear: {
|
||||||
imagePlayer.startPlaying()
|
self.imagePlayer.startPlaying()
|
||||||
}
|
}, disappear: {
|
||||||
.onDisappear {
|
|
||||||
if self.pausable {
|
if self.pausable {
|
||||||
imagePlayer.pausePlaying()
|
self.imagePlayer.pausePlaying()
|
||||||
} else {
|
} else {
|
||||||
imagePlayer.stopPlaying()
|
self.imagePlayer.stopPlaying()
|
||||||
}
|
}
|
||||||
if self.purgeable {
|
if self.purgeable {
|
||||||
imagePlayer.clearFrameBuffer()
|
self.imagePlayer.clearFrameBuffer()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
} else {
|
} else {
|
||||||
configure(image: imageManager.image!)
|
configure(image: imageManager.image!)
|
||||||
.onReceive(imageManager.$image) { image in
|
.onReceive(imageManager.$image) { image in
|
||||||
imagePlayer.setupPlayer(image: image)
|
self.imagePlayer.setupPlayer(image: image)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -94,7 +93,7 @@ public struct WebImage : View {
|
||||||
} else {
|
} else {
|
||||||
setupPlaceholder()
|
setupPlaceholder()
|
||||||
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
|
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
|
||||||
.onAppear {
|
.onPlatformAppear(appear: {
|
||||||
// Load remote image when first appear
|
// Load remote image when first appear
|
||||||
if self.imageManager.isFirstLoad {
|
if self.imageManager.isFirstLoad {
|
||||||
self.imageManager.load()
|
self.imageManager.load()
|
||||||
|
@ -105,14 +104,13 @@ public struct WebImage : View {
|
||||||
if self.imageManager.image == nil && !self.imageManager.isIncremental {
|
if self.imageManager.image == nil && !self.imageManager.isIncremental {
|
||||||
self.imageManager.load()
|
self.imageManager.load()
|
||||||
}
|
}
|
||||||
}
|
}, disappear: {
|
||||||
.onDisappear {
|
|
||||||
guard self.cancelOnDisappear else { return }
|
guard self.cancelOnDisappear else { return }
|
||||||
// When using prorgessive loading, the previous partial image will cause onDisappear. Filter this case
|
// When using prorgessive loading, the previous partial image will cause onDisappear. Filter this case
|
||||||
if self.imageManager.image == nil && !self.imageManager.isIncremental {
|
if self.imageManager.image == nil && !self.imageManager.isIncremental {
|
||||||
self.imageManager.cancel()
|
self.imageManager.cancel()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue