为什么字符串添加需要很长时间来构建?

Ami*_*mit 2 arrays ios swift

我正在添加文本UIlabel,以及它的性能成本(我使用此链接使用了构建时间分析器).我该如何优化此代码?

for value in model?.offerings ?? [] {
    offeringsLabel.text = offeringsLabel.text! + " | " +  (value.name ?? "") + "," +  (value.type ?? "")//this addition cost to performance
}
Run Code Online (Sandbox Code Playgroud)

我也尝试了,[ array].joined但这没有任何差异

Rob*_*ier 5

首先,针对潜在的问题.它为什么慢?+在我的经验中,链接是造成大量编译时性能问题的最常见原因.这是因为+有很多重载(我在4.2的stdlib中算了103).Swift不仅要证明+可以(String, String)按照您的意愿使用它.它必须证明没有其他可能的过载组合同样有效(如果有的话,它是模糊的和错误的).这不仅仅包括像(Int,Int)这样的简单情况.它还包括适用于(String,String)的复杂的基于协议的重载,但不像(String,String)那样精确:

static func + <Other>(lhs: String, rhs: Other) -> String 
    where Other : RangeReplaceableCollection, Character == Other.Element
Run Code Online (Sandbox Code Playgroud)

这需要很长时间,因为当你有一堆+链接在一起时,它是组合爆炸性的.每个子表达式都必须根据它可能返回的所有内容重新考虑.

怎么解决?首先,我不会for在这种情况下使用循环逐个构建一个字符串.只需将map每个Offering字符串连接到所需的字符串,然后将它们连接在一起

offeringsLabel.text = model?.offerings
    .map { "\($0.name ?? ""),\($0.type ?? "")" }
    .joined(separator: " | ")
Run Code Online (Sandbox Code Playgroud)

这不仅会更快地编译,而且IMO会更清楚你正在做什么.它也不需要!,这很好.(还有其他方法可以解决这个问题,但这是一个很好的副作用).

也就是说,这也表明你的模型中存在一个可能的问题.这是一个单独的问题,但我仍然会认真对待它.任何时候你有代码看起来像:

optionalString ?? ""
Run Code Online (Sandbox Code Playgroud)

你需要问一下,这真的是可选的吗?你真的对待一个名字与一个空名称不同吗?如果没有,我相信name并且type应该只是String而不是String?,然后这变得更加简单.

offeringsLabel.text = model?.offerings
    .map { "\($0.name),\($0.type)" }
    .joined(separator: " | ")
Run Code Online (Sandbox Code Playgroud)

此代码与您的代码略有不同.如果modelnil,你的代码留下offeringsLabel孤单.我的代码清除了文本.这提出了一个更深层次的问题:为什么你在运行这个代码时model是否为零?为什么是model可选的?你能否在数据中使它成为非可选项,或者你是否应该guard let model = model else { return }在此方法中使用它?

根据我的经验,过度复杂的Swift的常见原因是过度使用Optional.可选是非常重要和强大的,但你不应该使用它,除非你真的意味着"在这里没有任何价值是合法的,而不仅仅是'空'."