You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者شموخ الدوسري

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 03:35:57