Swift中如何在View的.position修饰符中使用模型存储的CGFloat值?
问题描述
我定义了一个Kid_animal SwiftData模型,包含动物名称、图片、位置坐标(posx、posy)等属性。尝试用.position修饰符结合这两个CGFloat类型的值实现动物图片的拖拽放置功能,但遇到两个核心问题:
.position修饰符无法正确识别posx和posy的值- 打印
animal.posx和animal.posy时,结果始终为0.0
视图代码
@Query var OwnAnimal : [Kid_animal] ForEach(OwnAnimal, id: \.self) { animal in if animal.Animal_drag == true { Image(animal.animal_image).resizable() .scaledToFit() .frame(width: 80, height: 80) .position(x: animal.posx, y: animal.posy) } else { Circle() .fill(Color.white) .opacity(0.4) .frame(width: 100, height: 100) .position(x : animal.posx, y: animal.posy) .onDrop(of: ["public.image"], isTargeted: nil) { providers, location in guard let provider = providers.first else { return false } if provider.canLoadObject(ofClass: UIImage.self) { _ = provider.loadObject(ofClass: UIImage.self) { image, error in if let image = image as? UIImage { let droppedImage = Image(uiImage: image) droppedImages[animal.animal_image] = droppedImage } else { withAnimation(Animation.easeInOut(duration: 0.2)) { droppedImages[animal.animal_image] = nil } } } } animal.Animal_drag = true return true } .overlay( droppedImages[animal.animal_image].map { $0.resizable() .scaledToFit() .frame(width: 80, height: 80) .position(x: animal.posx, y: animal.posy) } ) } }
模型代码
import SwiftData import CoreGraphics @Model class Kid_animal { var animal_name : String = "" var animal_image : String = "" var level : String = "" var animal_energy : String = "" var posx : CGFloat var posy : CGFloat var Animal_drag : Bool init(animal_name: String, animal_image: String, level: String, animal_energy: String, posx: CGFloat , posy: CGFloat,Animal_drag : Bool) { self.animal_name = animal_name self.animal_image = animal_image self.level = level self.animal_energy = animal_energy self.posx = posx self.posy = posy self.Animal_drag = Animal_drag } }
问题解决
1. 修复SwiftData对CGFloat的支持问题
SwiftData默认不支持CGFloat类型的持久化,这是导致posx/posy始终为0.0的核心原因。将模型中的posx/posy改为Double类型存储,通过计算属性转为CGFloat供视图使用:
import SwiftData @Model class Kid_animal { var animal_name: String = "" var animal_image: String = "" var level: String = "" var animal_energy: String = "" // 用Double存储位置,SwiftData原生支持 var posx: Double var posy: Double var Animal_drag: Bool init(animal_name: String, animal_image: String, level: String, animal_energy: String, posx: Double, posy: Double, Animal_drag: Bool) { self.animal_name = animal_name self.animal_image = animal_image self.level = level self.animal_energy = animal_energy self.posx = posx self.posy = posy self.Animal_drag = Animal_drag } // 提供CGFloat计算属性给视图调用 var cgPosx: CGFloat { CGFloat(posx) } var cgPosy: CGFloat { CGFloat(posy) } }
2. 正确修改SwiftData模型属性
不能直接修改animal.Animal_drag = true,必须通过modelContext执行修改,否则不会触发视图更新:
// 先在视图中注入modelContext @Environment(\.modelContext) private var modelContext // 替换原来的animal.Animal_drag = true modelContext.perform { animal.Animal_drag = true // 如果需要更新拖拽后的位置,同样在这里修改 // animal.posx = Double(newPosition.x) // animal.posy = Double(newPosition.y) }
3. 修正.position修饰符的调用
在视图中使用模型的计算属性cgPosx和cgPosy:
.position(x: animal.cgPosx, y: animal.cgPosy)
4. 检查初始化数据
确认创建Kid_animal实例时,传入的posx和posy不是默认的0.0,比如:
let newAnimal = Kid_animal( animal_name: "小猫", animal_image: "cat", level: "1", animal_energy: "100", posx: 150.0, posy: 200.0, Animal_drag: false ) modelContext.insert(newAnimal)
内容的提问来源于stack exchange,提问作者شموخ الدوسري
相关产品推荐
相关产品推荐

