我正在尝试创建一个简单的SWiftUI ScrollView,我可以在其中通过绑定设置和获取ScrollView边界偏移量的值。我有以下代码,可以作为ScrollView很好地编译和工作,但我无法实际设置和获取偏移量,并将其传播回托管ScrollView的ContentView。
我有以下几点:
struct MyScrollView<Content>: NSViewRepresentable where Content: View {
private var content: Content
let offset: Binding<CGFloat>
init(offset: Binding<CGFloat>, @ViewBuilder content: () -> Content) {
self.content = content()
self.offset = offset
}
func makeNSView(context: NSViewRepresentableContext<MyScrollView>) ->TheScrollView {
let view = TheScrollView(offset: offset)
view.hasVerticalScroller = true
view.hasHorizontalScroller = true
let document = NSHostingView(rootView: content)
document.translatesAutoresizingMaskIntoConstraints = false
view.documentView = document
return view
}
func updateNSView(_ view: TheScrollView, context: NSViewRepresentableContext<MyScrollView>) {
}
}
class TheScrollView: NSScrollView, ObservableObject{
private var subscriptions: Set<AnyCancellable> = []
var offset: Binding<CGFloat>
init(offset: Binding<CGFloat>){
self.offset = offset
super.init(frame: .zero)
NotificationCenter.default
.publisher(for: NSScrollView.boundsDidChangeNotification, object: self.contentView.documentView)
.sink() { _ in
let view = self.contentView
print(view.bounds.origin.y) // <- I do get this
self.offset.wrappedValue = view.bounds.origin.y // This does nothing
}
.store(in: &subscriptions)
}
required init?(coder: NSCoder){
fatalError("init(coder:) has not been implemented")
}
}
MyScrollView托管在contentView中,如下所示:
import SwiftUI
import Combine
struct ContentView: View{
@State var offset: CGFloat = 10.0{
didSet{
print("Offset \(offset)")
}
}
var body: some View{
MyScrollView(offset: $offset){
ZStack{
Rectangle().foregroundColor(.clear).frame(width: 1200, height: 1000)
Rectangle().foregroundColor(.blue).frame(width: 100, height: 100)
}
}
}
}
正如您所看到的,偏移值从@State变量传递到MyScollView,然后传递到TheScrollView,后者是NSScrollView的子类。从那里,我有一个简单的通知,以获得边界更改和设置绑定。但是,设置绑定对绑定中的实际值没有任何影响,而且它肯定不会传播回ContentView。此外,offset的地址在层次结构中向上更改,因此看起来我是在将绑定的绑定传递到TheScrollView中,而不是将原始绑定传递给offset,但我似乎无法修复它。
有没有人看到我做错了什么?谢谢!
发布于 2021-08-03 03:58:07
它是State
-它在body中使用时会更新,因此请使用如下所示:
struct ContentView: View{
@State var offset: CGFloat = 10.0
var body: some View {
VStack {
Text("Offset: \(offset)") // << here !!
MyScrollView(offset: $offset){
ZStack{
Rectangle().foregroundColor(.clear).frame(width: 1200, height: 1000)
Rectangle().foregroundColor(.blue).frame(width: 100, height: 100)
}
}
}
}
}
https://stackoverflow.com/questions/68631750
复制相似问题