What causes an 'AttributeGraph precondition failure' when using a TabView?

Viewed 2454

I had a single view application wrapped in a NavigationView where I populate data fetched from an API. However, I needed to add a profile section with a TabView and sometimes when I run the application, right when the launch screen is displayed, I get the following error (about once every three times I run/ debug the app) and the app crashes.

AttributeGraph precondition failure: invalid value type for attribute: 56028 (expected PlatformItemList, saw BridgedTableViewState)

The view that causes the error:

TabView {
    
    NavigationView {
        MainView()
    }
    .tabItem { VStack {
        Image(systemName: "list.dash")
        Text("main")
    }
    }
    
    NavigationView {
        ProfileView()
    }
    .tabItem { VStack {
        Image(systemName: "person.crop.circle")
        Text("profile")
    }
    }
}

I removed the TabView and the profile view and the app runs without any exceptions consistently, which is why I thought it was an issue with the TabView. I searched for documentation on AttributeGraph, PlatformItemList and BridgedTableViewState but found none.

3 Answers

I had a related error: AttributeGraph precondition failure: invalid value type for attribute: 431640 (saw PreferenceKeys, expected ViewList).

This error did not arise in an app with almost identical functional and database code but using UIKit and manually-constructed tab view, list view etc. Only in the SwiftUI version with SwiftUI structs for these views.

Removing the Persistence class and persistence management seemed to resolve the issue (I use a direct SQLite coding for persistence instead of CoreData).

The Xcode error messages could be more helpful.

I had experienced same problem. It was caused by combination of AnyView and NSViewRepresentable wrapper for WKWebView. Getting rid of AnyView by rewriting helper function with @ViewBuilder fixed the problem.

Problem:

func viewFunc() -> AnyView {
  switch self {
    case .case1: return AnyView(ListOfWebViewWrappers())
    default:     return AnyView(WaitView())
  }
}

Solution:

@ViewBuilder
func viewFunc() -> some View {
  switch self {
    case .case1: ListOfWebViewWrappers()
    default:     WaitView()
  }
}

the @ViewBuilder allows SwiftUI to properly track each view's identity and properly manage resources. More information about view's identity: https://developer.apple.com/videos/play/wwdc2021/10022/

I spent a lot of time dealing with precondition failure crashes in an app with multiple tab views. Is there any chance that one or more of your specific views (ProfileView or MainView) is also using a NavigationView? If so, that's probably the problem. Xcode will happily let you add NavigationViews in each new view, but it's not actually the way SwiftUI is meant to work. Since each TabView is wrapped in a NavView, then you shouldn't need/use a NavView inside of those views.

(Also, probably just cosmetic, but in the code snippet above there seems to be an extra close curly brace before your second Nav view.)

Related