swift - 如何在 SwiftUI 中渲染对象的新实例
问题描述
我有一组图像,并将每个图像渲染为可以拖动的卡片对象。我不想渲染每一个,因为这会导致性能问题。目前我正在使用 forEach 循环来渲染所有这些,但是我将如何渲染说两个,直到一个被删除。一旦一个被删除,我会在当前可见的卡片下渲染一个新实例。我不需要这个确切的实现,但有人可以指出我正确的方法。
import Photos
import SwiftUI
var imageToDelete = [PHAsset]()
struct ContentView: View {
var body: some View {
VStack{
// Here is where I'm rendering the card
ZStack{
ForEach(imageObjectGroup){ card in
CardView(card: card).padding(8)
}
}.zIndex(1.0)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
// You can ignore this I am converting the array item (PHAsset) to a UIImage so I can render it
func getAssetThumbnail(asset: PHAsset) -> UIImage {
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
var thumbnail = UIImage()
option.isSynchronous = true
manager.requestImage(for: asset, targetSize: CGSize(width: 350, height: 350), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in
thumbnail = result!
})
return thumbnail
}
// Card Object
struct CardView: View{
@State var card: ImageObject
let cardGradient = Gradient(colors: [Color.black.opacity(0), Color.black.opacity(0.5)])
var body: some View{
ZStack(alignment: .leading){
Image(uiImage: getAssetThumbnail(asset: card.image)).resizable().padding(8)
LinearGradient(gradient: cardGradient, startPoint: .top, endPoint: .bottom)
HStack {
Image("yes").resizable().aspectRatio(contentMode: .fit).frame(width: 150).opacity(Double(card.x/10 - 1))
Spacer()
Image("nope").resizable().aspectRatio(contentMode: .fit).frame(width: 150).opacity(Double(card.x/10 * -1 - 1))
}
//ZStack follows the coordinates of the card model
}.offset(x: card.x, y: card.y).rotationEffect(.init(degrees: card.degree)).gesture(
//Gesture recognizer updates coordinate values
DragGesture().onChanged { value in
card.x = value.translation.width
card.y = value.translation.height
card.degree = 7 * (value.translation.width > 0 ? 1 : -1)
}
//When user stops dragging
.onEnded { value in
withAnimation(.interpolatingSpring(mass: 1.0, stiffness: 50, damping: 8, initialVelocity: 0)){
switch value.translation.width {
case 0...100:
card.x = 0; card.degree = 0; card.y = 0
// Keep
case let x where x > 100:
card.x = 200; card.degree = 12
case (-100)...(-1):
card.x = 0; card.degree = 0; card.y = 0;
// Delete
case let x where x < -100:
card.x = -200; card.degree = -12
print(card.image)
imageToDelete.append(card.image)
PHPhotoLibrary.shared().performChanges( {
PHAssetChangeRequest.deleteAssets(imageToDelete as NSFastEnumeration)},
completionHandler: {
success, error in NSLog("Deletion prompt complete")
})
default: card.x = 0; card.y = 0
}
}
}
).cornerRadius(8)
}
}
解决方案
VStack
要渲染里面的每个视图,你需要使用一个惰性视图:
- 列表,它是
UITableView
. 这个的优点是能够使用许多表格视图功能,例如通过滑动删除单元格、重新排序等,但如果您有时不这样做,则很难自定义,例如当您想删除分隔符时等。在苹果列表教程中查看更多信息。我建议你通过所有苹果教程,因为它们非常好
List {
ForEach(imageObjectGroup){ card in
CardView(card: card).padding(8)
}.zIndex(1.0)
}
- 第二种方式是
LazyVStack
包裹在ScrollView
. 它的工作方式与VStack
加载单元格的方式相同,但以惰性方式加载。在本文中查看更多信息
ScrollView {
LazyVStack {
ForEach(imageObjectGroup){ card in
CardView(card: card).padding(8)
}.zIndex(1.0)
}
}
ps 我不知道你为什么用 包装你的卡ZStack
,这里是多余的
推荐阅读
- deep-learning - 有没有办法避免车牌中不需要的文本?
- hibernate - hibernate SessionImpl get(Class) 中的性能下降
5.2.5.version 中的 entityClass, Serializable id) 方法与 3.6.10 相比 - django - 确保至少选中一个复选框 - Django Forms
- python - 如何根据某些条件迭代和计算每个分类值
- python - 多处理因大量输入而被锁定
- python - UnboundLocalError:分配前引用的局部变量“pin”
- redis - 在 Redis 中存储访问令牌
- plot - 当应该显示为一个条时,计数图将相同的名称值显示为不同的条。我应该如何解决这个问题?
- python - Pyinstaller:在转换为 exe 时无法复制 Python-can 模块
- javascript - 替换文本区域内的内容