fix FlexImage
This commit is contained in:
parent
9f6f3eb6b2
commit
6b3273ad2f
@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user