Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Runtime error: precondition failure: attribute failed to set an initial value

I have a view BugSplitView which works fine alone but causes a

precondition failure: attribute failed to set an initial value

error when navigated to in either preview or the simulator.

The view has an upper part (Color) and a lower part (Color) separated by a horizontal button bar and laid out using the GeometeryReader and a split state. When it is the destination of NavigationButton it doesn't show properly in the Preview and reports the assertion above when run in the simulator. Remove the BugButtonBar and it works. Got me stumped! Help.

import SwiftUI

struct BugSplitView: View {
    @State var split : CGFloat = 0.75
    var buttons : [BugButtonBar.Info]{
        [BugButtonBar.Info(title: "title", imageName: "text.insert"){}]
    }
    var body: some View {
        GeometryReader{ g in
            VStack(spacing: 0){
                Color.gray
                    .frame(width: g.size.width, height: (g.size.height) * self.split)
                VStack{
                    BugButtonBar(infos: self.buttons)
                    Color(white: 0.3)
                }
                    .frame(height: (g.size.height) * (1 - self.split))
            }
        }.edgesIgnoringSafeArea(.all)
    }
}


struct BugButtonBar : View{

    struct Info : Identifiable {
        var id = UUID()
        var title : String
        var imageName : String
        var action: () -> Void
    }

    var infos : [Info]
    func color() -> Color{
        Color.black
    }
    var body: some View {
        HStack(){
            Spacer()
            ForEach(self.infos){ info in
                Button(action: info.action){
                    Text(info.title)
                }
                Spacer()
            }
        }
    }
}


struct ShowBugView : View{
    var body : some View{
        NavigationView {
            NavigationLink(destination: BugSplitView()){
                Text("Show Bug")
            }
        }
    }
}


struct BugSplitView_Previews: PreviewProvider {
    static var previews: some View {
        Group{
            BugSplitView()
            ShowBugView()
        }
    }
}
like image 416
Rumbles Avatar asked Oct 26 '19 18:10

Rumbles


4 Answers

The problem is that your buttons are declared as computed property. To solve the crash declare them like this:

var buttons = [BugButtonBar.Info(title: "title", imageName: "text.insert"){}]
like image 66
LuLuGaGa Avatar answered Nov 17 '22 03:11

LuLuGaGa


Turns out the id property of struct Info was the problem. Changed it to a computed property as follows:

var id : String {
   title + imageName
}

Great example of why I love/hate SwiftUI.

like image 4
Rumbles Avatar answered Nov 17 '22 03:11

Rumbles


For me it was displayMode inline in navigation bar title. Removing it fixes this problem.

Crash

.navigationBarTitle("Title", displayMode: .inline)

No crash

.navigationBarTitle("Title")
like image 4
Alex Avatar answered Nov 17 '22 05:11

Alex


Since it seems that this error - which can't be directly debugged - can be caused by so many different issues, I figured I'd throw my case up here too.

In my case, the error I was getting was:

precondition failure: attribute failed to set an initial value - 128

The issue was that I was attempting to present a sheet on a VStack that contained a NavigationView inside of it, like the below:

var body: some View {
    VStack(alignment: .center) {
        if /* some condition */ {
            /* some other content */
        } else {
            NavigationView {
                /* view content */
            }
        }
    }.sheet(isPresented: /* Binding value */) { 
        /* sheet content */
    }
}

The fix was to make sure that the sheet was being presented on the NavigationView instead:

var body: some View {
    NavigationView {
        VStack(alignment: .center) {
            if /* some condition */ {
                /* some other content */
            } else {
                /* view content */
            }
        }
    }.sheet(isPresented: /* Binding value */) { 
        /* sheet content */
    }
}

Seems obvious in hindsight, but it would have been nice to get a bit more information when the crash occurred in the first place.

like image 2
scorpiondev Avatar answered Nov 17 '22 03:11

scorpiondev