Write better: let bounds = p != nil ? geometry[p!.bounds] : .zero

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)
                .frame(width: bounds.size.width, height: bounds.size.height)
                .offset(x: bounds.minX, y: bounds.minY)
                .animation(.easeInOut(duration: 1.0))

“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

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

I don't think there's a possibility for p to be nil

I see. Better to analyze the whole thing and write correctly :+1:

        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?

Thanks for this discussion. Good to know the full range of implication.

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.