Hi,
I love the new new ScrollViewReader, as it enables to scroll to an arbitrary position.
However I would like to use it with lists, especially the new Expanding Lists, as outlines (like NSOutlineView) with some sort of bookmarks are critical for an app that I’m porting to iOS.
Is that possible in any way, or are we, for now, limited to scroll views with nested ForEachs?
Thanks, and great work.
Post
Replies
Boosts
Views
Activity
Hi,
In iPadOS can we use a .focusedSceneValue, defined from a command/Button inside a Scene, from inside the .command modifier attached to the scene?
Like this:
@main
struct test_focusedSceneValueApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.commands {
NavigationCommands()
}
}
}
struct NavigationCommands: Commands {
@FocusedValue(\.filterAction) var filterAction
var body: some Commands {
CommandMenu("Navigate") {
Button("Test focusedSceneValue") {
filterAction?()
}
.keyboardShortcut("5")
}
}
}
struct ContentView: View {
@FocusState var isFiltering: Bool
@State private var focusField: String = "***** field *****"
var body: some View {
TextField("***** focus", text: $focusField)
.focused($isFiltering)
.focusedSceneValue(\.filterAction) {
print("test successful")
isFiltering = true
}
}
This code is almost the same from the sample code from the documentation, however I can only retrieved nil values from the @FocusedValue and not the defined value.
Thanks.
Hi,
Does anyone knows if it is possible (or there are plans) to enable associating a .searchable modifier with a keyboard shortcut?
It seems a no brainer and very useful for iPadOS or Catalyst.
Thanks
Hi,
It seems that there's a bug in the iOS and iPadOS 16 betas (i've not test in macOS 13 yet), that when after updating a List data source with a bigger array, scrolling to a row of an offset bigger than the previous data array, with ScrollViewProxy, will crash the app with an EXC_BREAKPOINT (code=1, subcode=0x1099d6004) error.
Below I attached a sample code to reproduce the crash. In it when opening there's an empty list. When pressing the "Randomize & Select Last" button at the top, the list will be filled with 5 random UUIDs, followed by scrolling to the last row. The app will crash on the second try, when it will try to scroll to an offset bigger than the previous data array (the last row).
As a control there's an "Randomize & Select Random" button that will behave more or less like the "Randomize & Select Last" button but will choose a random row to select and scroll. It will only crash if this select row if of an offset bigger that the size of the previous array.
This doesn't happen in iOS 15.
I've already posted the Radar as FB11302966, however if someone has any toughs on how to solve this problem (or what I'm doing wrong) they are welcome.
Sample code:
///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() }
//Select the last element of the array/list.
//This will make sure that the scrollTo will go to the end
let newSelection = newData.last
//Update STate for the new values
data = newData
selection = newSelection
} label: {
Text("Randomize & Select Last")
}
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
if let selection {
proxy.scrollTo(selection)
}
})
}
}
}
}