From 9f6f3eb6b284f5c3760b253027cd60cb6ee84ab7 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Tue, 15 Apr 2025 15:37:14 +0800 Subject: [PATCH] fix view --- dimensionhub/Core/CacheManager.swift | 8 ++- dimensionhub/Views/FlexImage.swift | 82 +++++++++++++++++++++++++++- dimensionhub/dimensionhubApp.swift | 4 +- 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/dimensionhub/Core/CacheManager.swift b/dimensionhub/Core/CacheManager.swift index ddeda8a..fb9e82b 100644 --- a/dimensionhub/Core/CacheManager.swift +++ b/dimensionhub/Core/CacheManager.swift @@ -77,13 +77,13 @@ final class CacheManager { } // 保存文件到缓存 - private func saveCacheFile(filename: String, data: Data) throws { + func saveCacheFile(filename: String, data: Data) throws { let fileURL = cacheDir.appendingPathComponent(filename) try data.write(to: fileURL) } // 下载图片 - private func downloadImage(from urlString: String) async throws -> Data? { + func downloadImage(from urlString: String) async throws -> Data? { guard let url = URL(string: urlString) else { return nil } @@ -106,6 +106,10 @@ final class CacheManager { return sha256(str: urlString) + "." + url.pathExtension.lowercased() } + func getCacheFileName(url: URL) -> String { + return sha256(str: url.absoluteString) + "." + url.pathExtension.lowercased() + } + private func sha256(str: String) -> String { let data = Data(str.utf8) var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) diff --git a/dimensionhub/Views/FlexImage.swift b/dimensionhub/Views/FlexImage.swift index 62a53f7..3ed1e51 100644 --- a/dimensionhub/Views/FlexImage.swift +++ b/dimensionhub/Views/FlexImage.swift @@ -72,9 +72,89 @@ struct FlexImage: View { } } } +} + +class ImageCache { + static let shared = ImageCache() + private let cache = NSCache() + 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 { + case empty + case success(Image) + case failure(Error) +} + +struct MyAsyncImage: View { + let url: URL? + @State private var phase: FlexImagePhase = .empty + @ViewBuilder let content: (FlexImagePhase) -> Content + + init(url: URL?, @ViewBuilder content: @escaping (FlexImagePhase) -> Content) { + self.url = url + self.content = content + } + + var body: some View { + content(phase) + .task(id: url) { + guard let url else { + return + } + + phase = .empty + do { + if let cachedImage = ImageCache.shared.image(for: url) { + phase = .success(Image(uiImage: cachedImage)) + return + } + + let (data, _) = try await URLSession.shared.data(from: url) + if let image = await decodeImageData(data) { + ImageCache.shared.cacheImage(image, for: url) + phase = .success(Image(uiImage: image)) + } else { + phase = .empty + } + } catch { + phase = .failure(error) + } + } + } + + private func decodeImageData(_ data: Data) async -> UIImage? { + await Task.detached { + UIImage(data: data) + }.value + } +} + +// 使用示例 +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 { - //FlexImage() + ContentView() } diff --git a/dimensionhub/dimensionhubApp.swift b/dimensionhub/dimensionhubApp.swift index f2e2dc8..60f8cd6 100644 --- a/dimensionhub/dimensionhubApp.swift +++ b/dimensionhub/dimensionhubApp.swift @@ -68,7 +68,9 @@ struct dimensionhubApp: App { class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { - registerForPushNotifications() + Task.detached { + await self.registerForPushNotifications() + } return true }