今天在调试一个应用崩溃的问题的时候,发现有个sheet弹出后,被反复执行了多次。于是询问AI怎么回事。
原始的代码是这样的
.sheet(isPresented: $showAITranslationGuideView) {
let xtTransUnits: [XTTransUnit] = {
let xtTransUnits = Xliff_Tool.getXTTransUnits(from: trees)
return xtTransUnits.filter { $0.target == nil || $0.target?.isEmpty == true }
}()
AITranslationView(xtTransUnits: xtTransUnits)
}
询问AI啥原因,AI是这么回答的。
.sheet(isPresented: $showAITranslationGuideView)为什么会多次执行?
在 .sheet(isPresented: $showAITranslationGuideView) 代码块中,每次 showAITranslationGuideView 状态变化时都会重新执行闭包内的代码。这里的问题是 xtTransUnits 的计算被放在了视图构建的闭包中,而不是在实际需要时才执行。
建议将这些逻辑移到 AITranslationView 的初始化或 onAppear 中。以下是修改建议:
.sheet(isPresented: $showAITranslationGuideView) {
AITranslationView(trees: trees)
}
然后在 AITranslationView 中处理数据:
struct AITranslationView: View {
let trees: [Tree<IDTree>]
@State private var xtTransUnits: [XTTransUnit] = []
var body: some View {
// 你的视图内容
.onAppear {
xtTransUnits = getXTTransUnits(from: trees)
.filter { $0.target == nil || $0.target?.isEmpty == true }
}
}
}
这样可以确保计算只在实际需要时执行一次。
需要注意的是,AI的解释是对的,但是不是真正的原因。但是解法又同样是对的。只要移出这个初始化的代码之后,的确就不会重复计算了。
我认为真正原因是这样的。像.sheet(isPresented: $showAITranslationGuideView)的sheet,是在View初始化时就会被生成的。它是不变的。这就是为什么还有一个同名的但是使用Optional的sheet,那个才是动态的。但是我这里面的代码,在sheet使用前重新进行了计算。这导致原本应该只能是静态的sheet,变成了动态的,从而导致它从新被加载,而这种情形,其实是为定义的,因为这里不应该使用动态的。这个才是出错的真正原因。