fix FlexImage

This commit is contained in:
anlicheng 2025-04-15 15:49:05 +08:00
parent 9f6f3eb6b2
commit 6b3273ad2f

View File

@ -28,11 +28,9 @@ struct FlexImage: View {
let cacheManager = CacheManager.shared let cacheManager = CacheManager.shared
if let data = cacheManager.readFileContents(urlString: urlString) { if let data = cacheManager.readFileContents(urlString: urlString) {
print("url: \(urlString), hit cache")
self.mode = .local(data) self.mode = .local(data)
} else { } else {
Task.detached {
await cacheManager.preloadImage(url: urlString)
}
self.mode = .remote(urlString) self.mode = .remote(urlString)
} }
} }
@ -40,7 +38,7 @@ struct FlexImage: View {
var body: some View { var body: some View {
switch self.mode { switch self.mode {
case .remote(let url): case .remote(let url):
AsyncImage(url: URL(string: url)) { phase in FlexAsyncImage(url: URL(string: url)) { phase in
switch phase { switch phase {
case .empty: case .empty:
ProgressView() ProgressView()
@ -50,7 +48,7 @@ struct FlexImage: View {
.aspectRatio(contentMode: .fill) .aspectRatio(contentMode: .fill)
.frame(width: width, height: height) .frame(width: width, height: height)
.clipped() .clipped()
default: case .failure:
Image(placeholder) Image(placeholder)
.resizable() .resizable()
.aspectRatio(contentMode: .fill) .aspectRatio(contentMode: .fill)
@ -72,28 +70,16 @@ struct FlexImage: View {
} }
} }
} }
}
class ImageCache {
static let shared = ImageCache()
private let cache = NSCache<NSURL, UIImage>()
func image(for url: URL) -> UIImage? {
cache.object(forKey: url as NSURL)
}
func cacheImage(_ image: UIImage, for url: URL) {
cache.setObject(image, forKey: url as NSURL)
}
} }
enum FlexImagePhase { enum FlexImagePhase {
case empty case empty
case success(Image) case success(Image)
case failure(Error) case failure
} }
struct MyAsyncImage<Content: View>: View { struct FlexAsyncImage<Content: View>: View {
let url: URL? let url: URL?
@State private var phase: FlexImagePhase = .empty @State private var phase: FlexImagePhase = .empty
@ViewBuilder let content: (FlexImagePhase) -> Content @ViewBuilder let content: (FlexImagePhase) -> Content
@ -110,22 +96,27 @@ struct MyAsyncImage<Content: View>: View {
return return
} }
let cacheManager = CacheManager.shared
phase = .empty phase = .empty
do { do {
if let cachedImage = ImageCache.shared.image(for: url) { if let data = cacheManager.readFileContents(urlString: url.absoluteString),
let cachedImage = await decodeImageData(data) {
phase = .success(Image(uiImage: cachedImage)) phase = .success(Image(uiImage: cachedImage))
return return
} }
let (data, _) = try await URLSession.shared.data(from: url) let (data, _) = try await URLSession.shared.data(from: url)
if let image = await decodeImageData(data) { if let image = await decodeImageData(data) {
ImageCache.shared.cacheImage(image, for: url) let cacheFilename = cacheManager.getCacheFileName(url: url)
try? cacheManager.saveCacheFile(filename: cacheFilename, data: data)
phase = .success(Image(uiImage: image)) phase = .success(Image(uiImage: image))
} else { } else {
phase = .empty phase = .empty
} }
} catch { } catch {
phase = .failure(error) phase = .failure
} }
} }
} }
@ -137,24 +128,6 @@ struct MyAsyncImage<Content: View>: View {
} }
} }
// 使
struct ContentView: View {
var body: some View {
MyAsyncImage(url: URL(string: "https://lain.bgm.tv/pic/cover/l/60/fe/358801_WuBx6.jpg")) { phase in
switch phase {
case .empty:
ProgressView()
case .success(let image):
image
.resizable()
.scaledToFit()
case .failure(let error):
Text("Error: \(error.localizedDescription)")
}
}
}
}
#Preview { #Preview {
ContentView() FlexImage(urlString: "https://lain.bgm.tv/pic/cover/l/60/fe/358801_WuBx6.jpg", width: 80, height: 80, placeholder: "ph_img_big")
} }