mica
mica

Reputation: 4308

SwiftUI crashes with "precondition failure: attribute failed to set an initial value: 85"

I try to build a view which has a different layout for landscape and portrait.

I did it like this:

class ViewModel : ObservableObject
{
    @Published var name  = "Name"
}

struct ContentView: View {
  var body: some View {
    NavigationView{
      List{
        NavigationLink(destination: TEST(vm: ViewModel() ) ){Text ("TEST")}
      }
    }
  }
}

struct TEST: View {
  @ObservedObject var vm : ViewModel

  var body: some View {
    GeometryReader{ geometry in
      if  geometry.size.height > geometry.size.width {
        TEST_Vertical(vm: self.vm)
      } else {
        TEST_Horicontal(vm: self.vm)
      }
    }
  }
}

struct TEST_Horicontal: View {
  @ObservedObject var vm : ViewModel

    var body: some View {
      HStack{
        Text("left \(vm.name)")
        Spacer()
        Text("right")
      }
    }
  }

struct TEST_Vertical: View {
  @ObservedObject var vm : ViewModel
  var body: some View {
    VStack{
      Text("top")
      Text("\(vm.name)")
      Spacer()
      Text("bottom")
    }
  }
}

Unfortunately the app crashes clicking on the Navigationlink.

What am I doing wrong or is this a known bug?

Upvotes: 3

Views: 524

Answers (1)

Asperi
Asperi

Reputation: 258285

The crash happens because at start of NavigationLink transition GeometryReader returns CGSize.zero and in next update phase real size, so in-body view is changed on-the-fly that is not expected. Probably it is a bug.

You might consider the following workaround (or something like that, eg. use .hidden() conditionally). Tested with Xcode 11.4 / iOS 13.4 (I'm not hurry in env update).

struct TEST: View {
  @ObservedObject var vm : ViewModel

  var body: some View {
    GeometryReader{ geometry in
        ZStack {
            TEST_Vertical(vm: self.vm)
               .opacity(geometry.size.height >= geometry.size.width ? 1 : 0)
            TEST_Horicontal(vm: self.vm)
              .opacity(geometry.size.height < geometry.size.width ? 1 : 0)
        }
    }
  }
}

Upvotes: 2

Related Questions