How to debug precondition failure in Xcode?
I had a TabView containing a view that used a List.
When switching tabs, my app was crashing with a similar error:
"precondition failure: attribute failed to set an initial value: 99"
This crashed:
var body: some View {
TabView {
ListView()
.tabItem {
Image(systemName: "list.dash")
Text("List")
}
Wrapping the ListView in a NavigationView fixed the crash.
I saw this use of NavigationView on "Swift Live – 007 SwiftUI TabView && List" by Caleb Wells.
https://youtu.be/v1A1H1cQowI
https://github.com/calebrwells/A-Swiftly-Tilting-Planet/tree/master/2019/Live%20Streams/TabView%20List
This worked:
var body: some View {
TabView {
NavigationView { ListView() }
.tabItem {
Image(systemName: "list.dash")
Text("List")
}
Testing Swift code with preconditions
You test Swift methods that have preconditions by only testing behavior with inputs that meet those preconditions. The behavior when the precondition is not met is clear without further testing, since preconditions are baked into the standard library.
If you doubt you've correctly specified a precondition, you can pull out the precondition expression into a Boolean function, then test that for correctly discerning valid from invalid inputs.
However, you can create for yourself what you wish for here:
An option to generate exceptions on precondition/assertion failures would do the trick: one would turn it on in debug builds, and turn it off in release builds.
Instead of calling Apple's precondition
, you can write your own function, say, require
. This could be conditionally compiled to act as you wish. You would then use this everywhere you'd otherwise be using precondition
.
Difference between precondition and assert in swift?
assert
is for sanity checks during testing, whereas precondition
is for guarding against things that, if they happen, would mean your program just could not reasonably proceed.
So for example, you might put an assert
on some calculation having sensible results (within some bounds, say), to quickly find if you have a bug. But you wouldn’t want to ship with that, since the out-of-bound result might be valid, and not critical so shouldn’t crash your app (suppose you were just using it to display progress in a progress bar).
On the other hand, checking that a subscript on an array is valid when fetching an element is a precondition
. There is no reasonable next action for the array object to take when asked for an invalid subscript, since it must return a non-optional value.
Full text from the docs (try option-clicking assert
and precondition
in Xcode):
Precondition
Check a necessary condition for making forward progress.
Use this function to detect conditions that must prevent the
program from proceeding even in shipping code.
In playgrounds and -Onone builds (the default for Xcode's Debug
configuration): ifcondition
evaluates to false, stop program
execution in a debuggable state after printingmessage
.In -O builds (the default for Xcode's Release configuration):
ifcondition
evaluates to false, stop program execution.In -Ounchecked builds,
condition
is not evaluated, but the
optimizer may assume that it would evaluate totrue
. Failure
to satisfy that assumption in -Ounchecked builds is a serious
programming error.
Assert
Traditional C-style assert with an optional message.
Use this function for internal sanity checks that are active
during testing but do not impact performance of shipping code.
To check for invalid usage in Release builds; seeprecondition
.
In playgrounds and -Onone builds (the default for Xcode's Debug
configuration): ifcondition
evaluates to false, stop program
execution in a debuggable state after printingmessage
.In -O builds (the default for Xcode's Release configuration),
condition
is not evaluated, and there are no effects.In -Ounchecked builds,
condition
is not evaluated, but the
optimizer may assume that it would evaluate totrue
. Failure
to satisfy that assumption in -Ounchecked builds is a serious
programming error.
Track and fix swiftUI crash (saw PreferenceKeys, expected ViewList)?
It's difficult to say definitively what the issue is here, but this line:
DispatchQueue.main.async{
self.listID = UUID().uuidString //Void apple SwiftUI big in AttributeGraph cycle ( seems it worked by Jack )
}
Leads me to think you may have lurking instabilities caused by overlapping view hierarchy updates.
There's a good discussion of how arbitrarily updating your view ids can lead to issues in this week's 2021 WWDC (Demystify SwiftUI): https://developer.apple.com/wwdc21/10022
You've also got this line:
}//end of geo
.id( self.listID )
Which forces the geo view to update itself. That coupled with the above .onAppear reset of the listID is causing your entire view hierarchy to constantly update itself (and be unstable).
Here's another guide about how misplaced state changes can cause unstable behavior:
https://swiftui-lab.com/state-changes/
Related Topics
Controlling Size of Texteditor in Swiftui
How to Avoid That My Swift Async Method Runs on the Main Thread in Swiftui
Realitykit as a Framework to Build 3D Nonar Apps
Flip Arfaceanchor from Left-Handed to Right-Handed Coordinate System
Nsdata Contentsofurl Constructor Returns Nil
Collectionview Not Display Data After Parsing JSON
Save & Retrieve Tableviewcell Checkmark Using Nsuserdefaults in Swift
Executing Text-To-Speech in Order
Cannot Invoke 'Filter' with an Argument List of Type '((_) -> _)'
How to Compare Just the Time of a Date in Swift
Scenedidload Being Called Twice
Building a Spritekit/Gamekit Leaderboard Within a Specific Scene
How to Create an Array with Incremented Values in Swift
Why Does Adding 'Dynamic' Fix My Bad Access Issues
How to Set Font Size of Sklabelnode to Fit in Fixed Size (Swift)