问题描述
在SwiftUI中,我的使用场景为根据“压缩率”字段,返回本地化的字符串。
在代码中,使用compressionTips()方法,返回String字符串,在Text中使用LocalizedStringKey初始化方法,显示本地化的字符串。
func compressionTips() -> String {
let rate = appStorage.imageCompressionRate
if rate <= 0.2 {
return "Lowest"
} else if rate <= 0.4 {
return "Low Quality"
} else if rate <= 0.6 {
return "Balanced"
} else if rate <= 0.8 {
return "High Quality"
} else {
return "Lossless"
}
}
Text(LocalizedStringKey:compressionTips())
但是,这个代码会导致长时间的编译。

并且输出Xcode报错:
The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
把compressionTips()方法拆分,仍然无法解决长时间编译的问题:
let tip = compressionTips()
Text(LocalizedStringKey:tip)
问题原因
当使用LocalizedStringKey方法时:
Text(LocalizedStringKey(compressionTips()))
或String(localized:)方法
Text(String(localized: compressionTips()))
都可能在SwiftUI的视图树中引发编译卡顿,尤其是在 compressionTips() 是依赖绑定数据(如 @ObservedObject, @State, @AppStorage)的时候。
解决方案
应该避免视图内容调用逻辑函数,可以将compressionTips()的调用结果提前计算为局部变量或计算属性,再传入Text。
推荐使用计算属性解决这一问题:
struct SettingsView: View {
@ObservedObject var appStorage = AppStorage.shared
var compressionLocalizedKey: LocalizedStringKey {
let rate = appStorage.imageCompressionRate
if rate <= 0.2 {
return "compression.level.lowest"
} else if rate <= 0.4 {
return "compression.level.low"
} else if rate <= 0.6 {
return "compression.level.balanced"
} else if rate <= 0.8 {
return "compression.level.high"
} else {
return "compression.level.lossless"
}
}
var body: some View {
VStack {
Text(compressionLocalizedKey) // 编译无压力,支持本地化
}
}
}

这个方案可以解决本地化字符串导致编译卡顿的问题。
因此compressionLocalizedKey是一个简单的属性,SwiftUI编译器更容易处理。
Text直接接收LocalizedStringKey,这是SwiftUI本地化字符串的首选用法。
避免了运行时字符串查找和嵌套函数调用,降低视图 diffing 成本。