This commit is contained in:
anlicheng 2025-04-15 15:37:14 +08:00
parent 260bf6017f
commit 9f6f3eb6b2
3 changed files with 90 additions and 4 deletions

View File

@ -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) let fileURL = cacheDir.appendingPathComponent(filename)
try data.write(to: fileURL) 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 { guard let url = URL(string: urlString) else {
return nil return nil
} }
@ -106,6 +106,10 @@ final class CacheManager {
return sha256(str: urlString) + "." + url.pathExtension.lowercased() 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 { private func sha256(str: String) -> String {
let data = Data(str.utf8) let data = Data(str.utf8)
var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))

View File

@ -72,9 +72,89 @@ 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 {
case empty
case success(Image)
case failure(Error)
}
struct MyAsyncImage<Content: View>: 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 { #Preview {
//FlexImage() ContentView()
} }

View File

@ -68,7 +68,9 @@ struct dimensionhubApp: App {
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
registerForPushNotifications() Task.detached {
await self.registerForPushNotifications()
}
return true return true
} }