我有一个自定义 TabView,我想绑定(bind)到一个状态来更改选项卡。我还想检测用户是否再次点击相同的选项卡以滚动到该 View 的顶部。
当我使用绑定(bind)时,不会调用 didSet。 onChange 没有被调用,因为值没有改变,并且 onReceive 没有给我旧的值来比较。
有什么想法吗? (尽量避免使用已发布的属性)
struct ContentView: View {
@State private var scrollToTop1: Bool = false
@State private var scrollToTop2: Bool = false
@State private var selectedTab: Int = 1
var body: some View {
ZStack(alignment: .bottom) {
TabView(selection: $selectedTab) {
NavigationView {
View1(scrollToTop: $scrollToTop1)
}
.tag(1)
NavigationView {
View2(scrollToTop: $scrollToTop2)
}
.tag(2)
}
.onReceive(Just(selectedTab)) { [oldValue = selectedTab] newValue in
print("Old: \(oldValue)") //Shows newValue
print("New: \(newValue)")
if oldValue == newValue {
switch selectedTab {
case 1:
scrollToTop1.toggle()
case 2:
scrollToTop2.toggle()
default:
break
}
}
}
TabBar(selectedTab: $selectedTab)
}
}
}
struct TabBar: View {
@Binding var selectedTab: Int
var body: some View {
HStack {
TabItem(selectedTab: $selectedTab, text: "View 1", tab: 1)
TabItem(selectedTab: $selectedTab, text: "View 2", tab: 2)
}
.background(Color.green)
}
}
struct TabItem: View {
@Binding var selectedTab: Int
let text: String
let tab: Int
var body: some View {
Button {
selectedTab = tab
} label: {
Text(text)
}
.frame(maxWidth: .infinity)
.frame(height: 50)
}
}
最佳答案
我认为这是自定义绑定(bind)
的一个很好的场景,您可以在设置之前拦截该值并进行比较:
struct ContentView: View {
@State private var scrollToTop1: Bool = false
@State private var scrollToTop2: Bool = false
@State private var selectedTab: Int = 1
var customBinding: Binding<Int> {
.init {
selectedTab
} set: { newValue in
print("New value: ", newValue)
if newValue == selectedTab {
print("Scroll to top")
}
selectedTab = newValue
}
}
var body: some View {
ZStack(alignment: .bottom) {
TabView(selection: customBinding) {
NavigationView {
Text("1")
}
.tag(1)
NavigationView {
Text("2")
}
.tag(2)
}
TabBar(selectedTab: customBinding)
}
}
}
struct TabBar: View {
@Binding var selectedTab: Int
var body: some View {
HStack {
TabItem(selectedTab: $selectedTab, text: "View 1", tab: 1)
TabItem(selectedTab: $selectedTab, text: "View 2", tab: 2)
}
.background(Color.green)
}
}
关于SwiftUI onReceive 是否可以获取oldValue?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74732777/