我真的被一些我认为应该相对容易的事情难住了,所以我需要在正确的方向上有一点小小的突破。我搜索了很多地方,但得到的要么是错误的信息,要么是过时的信息(很多!)。
我正在使用 Core Data 和 CloudKit 在用户设备之间同步数据。我将图像另存为附加到 CKRecord 的 CKAsset。效果很好。问题在于检索图像。我需要列表中每个独特实体(游戏)的图像。因此,我在 viewModel 上编写了一个方法,用于使用 CKAsset 检索记录。这有效(已验证),但我不知道如何获取图像并将其分配给 SwiftUI Image() View 。我当前的方法返回一个带有 UIImage 的闭包,如何将该图像设置为 foreach 中的 Image() 。或者任何其他解决方案表示赞赏。获取图像应该不难吧?
/// Returns the saved UIImage from CloudKit for the game or the default Image!
func getGameImageFromCloud(for game: Game, completion: @escaping (UIImage) -> Void ) {
// Every game should always have an id (uuid)!
if let imageURL = game.iconImageURL {
let recordID = CKRecord.ID(recordName: imageURL)
var assetURL = ""
CKContainer.default().privateCloudDatabase.fetch(withRecordID: recordID) { record, error in
if let error = error {
print(error.getCloudKitError())
return
} else {
if let record = record {
if let asset = record["iconimage"] as? CKAsset {
assetURL = asset.fileURL?.path ?? ""
DispatchQueue.main.async {
completion(UIImage(contentsOfFile: assetURL) ?? AppImages.gameDefaultImage)
}
}
}
}
}
} else {
completion(AppImages.gameDefaultImage)
}
}
这是我想显示每个游戏的图像的 ForEach(但这在多个地方都需要:
//Background Tab View
TabView(selection: $gamesViewModel.currentIndex) {
ForEach(gamesViewModel.games.indices, id: \.self) { index in
GeometryReader { proxy in
Image(uiImage: gamesViewModel.getGameImageFromCloud(for: gamesViewModel.games[index], completion: { image in
}))
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: proxy.size.width, height: proxy.size.height)
.cornerRadius(1)
}
.ignoresSafeArea()
.offset(y: -100)
}
.onAppear(perform: loadImage)
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.animation(.easeInOut, value: gamesViewModel.currentIndex)
.overlay(
LinearGradient(colors: [
Color.clear,
Color.black.opacity(0.2),
Color.white.opacity(0.4),
Color.white,
Color.systemPurple,
Color.systemPurple
], startPoint: .top, endPoint: .bottom)
)
.ignoresSafeArea()
TIA!
最佳答案
所以,让我们开始...将 ForEach
图像相关内部结构提取到 subview 中,例如(当然它不可测试,只是想法):
ForEach(gamesViewModel.games.indices, id: \.self) { index in
GeometryReader { proxy in
GameImageView(model: gamesViewModel, index: index) // << here !!
.frame(width: proxy.size.width, height: proxy.size.height)
.cornerRadius(1)
//.onDisappear { // if you think about cancelling
// gamesViewModel.cancelLoad(for: index)
//}
}
.ignoresSafeArea()
.offset(y: -100)
}
.onAppear(perform: loadImage)
现在是 subview 本身
struct GameImageView: View {
var model: Your_model_type_here
var index: Int
@State private var image: UIImage? // << here !!
var body: some View {
Group {
if let loadedImage = image {
Image(uiImage: loadedImage) // << here !!
.resizable()
.aspectRatio(contentMode: .fill)
} else {
Text("Loading...")
}
}.onAppear {
model.getGameImageFromCloud(for: model.games[index]) { image in
self.image = image
}
}
}
}
关于image - SwiftUI、CloudKit 和图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73260123/