onReceive (self.timer) bir NavigationView içinde çalışmıyor
ScrollviewYalnızca belirli bir yüksekliği geçtiğinde gösterilen özel bir başlığa sahip bu a sayfam var . Kullandığım GeometryReaderile onReceivesürekli güncel kaydırma yüksekliğini kontrol etmek için:
@State var userInfoUpateInterval = Timer.publish(every: 0.1, on: .current, in: .tracking).autoconnect()
@State var showHeader: Bool = false
var body: some View {
NavigationView {
ZStack(alignment: .top) {
ScrollView(.vertical) {
GeometryReader { geometry in
Text("User info component").onReceive(self.userInfoUpateInterval) { (_) in
self.onUserInfoLayoutChange(geometry)
}
}
VStack {
Text("content")
}.frame(width: UIScreen.screenWidth, height: 1500)
}
ProfileHeader(title: "user.userName", showHeader: $showHeader)
}
}
}
Kaydırma ve üstbilgi gizleme / gösterme ZStack, bir NavigationView. onReceiveartık tetiklenmiyor. Bir NavigationViewile değiştirirsem , ZStackher şey beklendiği gibi tekrar çalışır.
Bu Zamanlayıcının onReceive'in NavigationView sorusu içinde çalışmadığını gördüm, ancak koşullu bileşenim yok. Bu bir SwiftUI hatası mı yoksa yanlış bir şey mi yapıyorum?
Yanıtlar
İşte davanız için olası bir çözüm demosu. Xcode 11.4 / iOS 13.4 ile test edilmiştir (ve ileriye dönük uyumludur)
Buradaki fikir, zamanlayıcıyla değil, görünüm tercihleri tarafından okunan / izlenen görünüm konumu değişikliğine göre tepki vermektir.
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue: CGFloat { 0 }
static func reduce(value: inout Value, nextValue: () -> Value) {
value = value + nextValue()
}
}
struct DemoView: View {
@State var showHeader: Bool = false
var body: some View {
NavigationView {
ZStack(alignment: .top) {
ScrollView(.vertical) {
Text("User info component")
.background(GeometryReader {
Color.clear.preference(key: ViewOffsetKey.self,
value: -$0.frame(in: .named("scroll_area")).origin.y) }) VStack { Text("content") }.frame(maxWidth: .infinity, minHeight: 1500) }.coordinateSpace(name: "scroll_area") if showHeader { Text("ProfileHeader") } } } .onPreferenceChange(ViewOffsetKey.self) { self.showHeader = $0 > 200 // << your condition
}
}
}