young
(rtSwift)
1
I'm going over the fantastic swiftui-lab.com blog.
Is there a better way to write this:
let bounds = p != nil ? geometry[p!.bounds] : .zero
I change it to:
let bounds = p.map { geometry[$0.bounds] } ?? .zero
Is there any better way?
This is the whole func:
fileprivate func createBorder(_ geometry: GeometryProxy, _ preferences: [MyTextPreferenceData]) -> some View {
let p = preferences.first(where: { $0.viewIdx == self.activeIdx })
// let bounds = p != nil ? geometry[p!.bounds] : .zero
let bounds = p.map { geometry[$0.bounds] } ?? .zero
return RoundedRectangle(cornerRadius: 15)
.stroke(lineWidth: 3.0)
.foregroundColor(Color.green)
.frame(width: bounds.size.width, height: bounds.size.height)
.fixedSize()
.offset(x: bounds.minX, y: bounds.minY)
.animation(.easeInOut(duration: 1.0))
}
Karl
(👑🦆)
2
“better” is a matter of preference, but yes, I personally prefer the way you’ve written it (using Optional.map)
It is logically sound in its context here, but in general, p is not guaranteed to still be non‐nil when the force‐unwrap happens. It may have changed due to another thread, or as a side‐effect of any of the calls inside the ternary. The map variant is definitively safer to make a habit of.
1 Like
Lantua
4
I looked at the example.
-
I don't think there's a possibility for p to be nil. I'd just force unwrap p.
let p = preferences.first(...)!
-
Even if it's nil, that'd mean that there's no selection. It'd be much better to fade-out the data instead of snapping the box to .zero. Maybe something like this
guard let p = ... else {
return nil
}
Otherwise, what you're using LGMT.
FWIW, p being both local variable and struct is a very strong context. So it must be much more general than this to pose a problem.
1 Like
Yes, it is fine in that function and that is what I meant by “context”.
I said what I did because the question sounded like it was about which coding pattern is generally better to make a habit of writing. In that case it is significant that if let or map actually establish a strong reference and prevent the value from changing or vanishing before the conditional operation takes place; if x != nil together with x! does not.
1 Like
young
(rtSwift)
6
I don't think there's a possibility for p to be nil
I see. Better to analyze the whole thing and write correctly 
guard let p = preferences.first(where: { $0.viewIdx == self.activeIdx }) else {
// return nil // Error: 'nil' requires a contextual type
fatalError("activeIdx not found")
}
return nil doesn't compile.
But anyway if .first() should never return nil, then getting nil is better handled with fatalError?
young
(rtSwift)
7
Thanks for this discussion. Good to know the full range of implication.
Lantua
8
I see. I haven't tried it, though technically speaking, it'd be a correct program.
My guess is that the compiler couldn't infer the return type. It would be an Optional of some View, which is also View. Figuring out a way to make that work is probably way outside the scope of this thread.
If it's provably not nil, then you can just force unwrap.