More serioulsy this bug seems to be solved on iOS 16.4, as the scroll will happen and the app will not crash.
However the selection will not visually happen unless is made after the scroll has happened, by wrapping it inside a DispatchQueue.main.async call.
Does anyone has a better ideas how to do this?
Code sample follows:
///A simple data model for the demo. Only stores an UUID.
struct DataModel: Identifiable, Hashable {
let id: UUID = UUID()
var nameUUID: String {
id.uuidString
}
}
struct ContentView: View {
///Array with some data to show
@State private var data: [DataModel] = []
///Selected row
@State private var selection: DataModel?
var body: some View {
VStack(alignment: .leading) {
HStack {
//Create a new array for showing in the list.
//This array will be bigger than the last one.
//The selection will be the last element of the array (triggering the bug)
Button {
//Increment the size of the new List by 5
let numberElements = data.count + 5
//Create a new Array of DataModel with more 5 elements that the previous one
let newData = (0 ..< numberElements).map { _ in DataModel() }
//Update STate for the new values
data = newData
} label: {
Text("Randomize & Select Last")
}
Spacer()
Text(selection?.id.uuidString ?? "no selection")
Spacer()
//Create a new array for showing in the list.
//This array will be bigger than the last one.
//The selection will be the a random element of the array (only triggering the bug when the element is )
Button {
//Increment the size of the new List by 5
//If empty will start with 40 (reducing the odds of triggering the bug)
let numberElements = data.count == 0 ? 40 : data.count + 5
//Create a new Array of DataModel with more 5 elements that the previous one
let newData = (0 ..< numberElements).map { _ in DataModel() }
//Select a random element of the array/list.
//This will scroll if the element is 'inside' the previous list
//Otherwise will crash
let newSelection = newData.randomElement()
//Update State for the new values
data = newData
selection = newSelection
} label: {
Text("Randomize & Select Random")
}
}
.padding()
//MARK: ScrollViewReader and List
ScrollViewReader {
proxy in
List(data, selection: $selection) {
dataElement in
//Row (is only the UUID for the rows
Text(dataElement.id.uuidString)
.id(dataElement)
.tag(dataElement)
}
//action that fires when data changes
//it will scroll to the selection
.onChange(of: data, perform: { newValue in
let lastValue = newValue.last
proxy.scrollTo(lastValue)
DispatchQueue.main.async {
//Select the last element of the array/list.
self.selection = lastValue
}
})
}
}
}
}
Post
Replies
Boosts
Views
Activity
At least it will not be solved for a lack of trying.
Beta 7 still has the bug. I hope that at least in the release candidate is fixed. This could be app breaking.
Try using the .listRowBackground view modifier for changing the row background.
You will also need to provide the animation for highlighting the row if the selection is not permanent.
This bug seems now to be fixed.
Unfortunately .isSearching is read-only, it cannot me mutated.
If you try you get: Cannot assign to property: 'isSearching' is a get-only error.
Best regards
Hi,
For now try what is suggested in https://stackoverflow.com/a/68154005/1356575 . It's an hack but it works.
Best regards.
It seems that is a bug.
As described in the Bug Report that I sent to Apple (FB9163579):
As described in the docs .focusedSceneValue modifies this view by injecting a value that you provide for use by other views whose state depends on the focused scene.
One of the aims is to make available to the Scene commands some way to change the Scene view states. However it doesn't work. > These value are always nil, as if the view that is modified by .focusedSceneValue isn't in a Scene with focus.
The same happens if another view of the Scene tries to retrieve the value with @FocusedValue. In the code sample that I've attached a Button will execute the closure that is the value being shared. But if the Button is pressed with a keyboard shortcut @FocusedValue will be nil.
Sample project here.