I have a list displaying all integers from 1 to 1000. When the user taps the > button on the remote, I would like to advance by 50 items in that list. This is what I tried, but when I press the > button, I get the information that focused is not nil, but it doesn't get updated though.
struct ContentView: View {
@FocusState private var focused: Int?
var body: some View {
List(1..<1001) { i in
Button(action: {}) {
Text("\(i)")
}
.focused($focused, equals: i)
}
.onMoveCommand { direction in
switch direction {
case .right:
if focused == nil {
print("focused is nil")
} else {
print("focused is not nil")
focused! += 50
}
default:
break
}
}
.onChange(of: focused) { oldValue, newValue in
print(newValue)
}
}
}
What should I do? Thanks for your help
When you've got a big list, like with 1000 numbers, it won't load everything at once—it just shows what's needed. This is the Lazy loading nature of List in SwiftUI.
You can use a ScrollViewReader
and use its proxy to help you jump around the list, even to parts not shown yet:
struct ContentView: View {
@FocusState private var focused: Int?
var body: some View {
ScrollViewReader { proxy in
List(1..<1000, id: \.self) { i in
Button(action: {}) {
Text("\(i)")
}
.focused($focused, equals: i)
.id(i)
}
.onMoveCommand(perform: handleMoveCommand(proxy: proxy))
}
}
private func handleMoveCommand(proxy: ScrollViewProxy) -> (MoveCommandDirection) -> Void {
return { direction in
if direction == .right {
withAnimation {
let newFocus = (focused ?? 0) + 50
focused = newFocus
proxy.scrollTo(newFocus, anchor: .top)
}
}
}
}
}
When you press the right button, the list smoothly scrolls to number 50, even if it wasn't on the screen before. To do that, use proxy.scrollTo(50)
. And with focused = 50
, the list knows that number 50 is where the action's at now.
Try to avoid doing things like focused!
in your code as much as possible. It can cause crashes when the values are truly not present and you try to access them.