First, to the underlying question. Why is it slow? Chained +
is the single most common cause of massive compile-time performance issues in my experience. It's because +
has a lot of overloads (I count 103 in 4.2's stdlib). Swift doesn't just have to prove that +
can be used on (String, String)
as you want it to be. It has to prove there is no other possible overload combination that is equally valid (if there were, it'd be ambiguous and an error). That doesn't just include simple cases like (Int, Int). It also includes complicated protocol-based overloads that apply to (String, String), but aren't as precise as (String, String) like:
static func + <Other>(lhs: String, rhs: Other) -> String
where Other : RangeReplaceableCollection, Character == Other.Element
This takes a long time because it's combinatorially explosive when you have a bunch of +
chained together. Each sub-expression has to be reconsidered in light of everything it might return.
How to fix it? First, I wouldn't use a for
loop in this case to build up a string piece by piece. Just map
each Offering
to the string you want, and then join them together:
offeringsLabel.text = model?.offerings
.map { "\($0.name ?? ""),\($0.type ?? "")" }
.joined(separator: " | ")
Not only will this compile much more quickly, but it's IMO much clearer what you're doing. It also doesn't require a !
, which is nice. (There are other ways to fix that, but it's a nice side-effect).
That said, this is also pointing to a probable issue in your model. It's a separate issue, but I would still take it seriously. Anytime you have code that looks like:
optionalString ?? ""
you need to ask, should this really be Optional? Do you really treat a nil name differently than an empty name? If not, I believe that name
and type
should just be String
rather than String?
, and then this gets even simpler.
offeringsLabel.text = model?.offerings
.map { "\($0.name),\($0.type)" }
.joined(separator: " | ")
This code is has a slight difference from your code. When model
is nil
, your code leaves offeringsLabel
alone. My code clears the text. This raises a deeper question: why are you running this code at all when model
is nil? Why is model
optional? Could you either make it non-optional in the data, or should you have a guard let model = model else { return }
earlier in this method?
The common cause of over-complicated Swift in my experience is the over-use of Optional. Optional is incredibly important and powerful, but you shouldn't use it unless you really mean "having no value at all here is both legitimate, and different than just 'empty'."
??
— it has some problems with type inference checks during build. For reference, check here. – Larcherstruct Response:Codable { var offerings:[offerings]?
– Platinize??
in string concatenation line too. And you have just to help type inference, by extracting snippets with??
to variables andexplicitly
provide the type you're expecting. – Larcher