ios - Setting a shared title within a common Header View amongst Views; per Active View
问题描述
Goal: To use a common header View containing a shared title Text().
Scenario: I have multiple Views that share a common tab space within the one container tab View that contains a struct Header that is to be shared.
This is a (many : 1) scenario.
Note: I don't want to use a NavigationView because it screws up landscape mode. A simple small header View is fine. I just need to populate the shared Title space amongst the member Views.
I don't want to merely add duplicate headers (having exactly the same layout) for each member View.
Several ideas: I need the header to respond to the 'change of title' event so I can see the new title.
So I believe I could use 1) @Binder(each member View) --> @State (shared Header View) or
2) @Environment.
I don't know how I could fit #1 into this particular scenario.
So I'm playing with #2: Environment Object.
DesignPattern: Main Header View's title set by multiple Views so the Header View is not aware of the multiple Views:
I'm not getting the EnvironmentObject paradigm to work.
Here's the codes...
MainView:
import SwiftUI
// Need to finish this.
class NYTEnvironment {
var title = "Title"
var msg = "Mother had a feeling..."
}
class NYTSettings: ObservableObject {
@Published var environment: NYTEnvironment
init() {
self.environment = NYTEnvironment()
}
}
struct NYTView: View {
var nytSettings = NYTSettings()
@State var selectionDataSegmentIndex = 0
var bindingDataSourceSegment: Binding<Int> {
.init(get: {
selectionDataSegmentIndex
}, set: {
selectionDataSegmentIndex = $0
})
}
var body: some View {
let county = 0; let state = 1; let states = 2
VStack {
NYTHeaderView()
SegmentAndDataPickerVStack(spacing: 10) {
if let segments = Source.NYT.dataSegments {
Picker("NYT Picker", selection: bindingDataSourceSegment) {
ForEach(segments.indices, id: \.self) { (index: Int) in
Text(segments[index])
}
}.pickerStyle(SegmentedPickerStyle())
}
}
if selectionDataSegmentIndex == county {
NYTCountyView()
} else if selectionDataSegmentIndex == state {
NYTStateView()
} else if selectionDataSegmentIndex == states {
NYTStatesView()
}
Spacer()
}.environmentObject(nytSettings)
}
struct TrailingItem: View {
var body: some View {
Button(action: {
print("Info")
}, label: {
Image(systemName: "info.circle")
})
}
}
}
// ====================================================================================
struct NYTHeaderView: View {
@EnvironmentObject var nytSettings: NYTSettings
var body: some View {
ZStack {
Color.yellow
Text(nytSettings.environment.title)
}.frame(height: Header.navigationBarHeight)
}
}
Revision: I've added EnvironmentObject modifiers to the memberViews():
if selectionDataSegmentIndex == county {
NYTCountyView().environmentObject(NYTSettings())
} else if selectionDataSegmentIndex == state {
NYTStateView().environmentObject(NYTSettings())
} else if selectionDataSegmentIndex == states {
NYTStatesView().environmentObject(NYTSettings())
}
...
One of the member Views that's within the Main Container/Tab View (per above):
struct NYTCountyView: View {
@ObservedObject var dataSource = NYTCountyModel()
@EnvironmentObject var nytSettings: NYTSettings
...
...
}.onAppear {
nytSettings.environment.title = "Selected Counties"
if dataSource.revisedCountyElementListAndDuration == nil {
dataSource.getData()
}
}
Spacer()
...
}
Here's the compile-time error:
Modus Operandi: Set the title w/in header per member View upon .onAppear().
Problem: I'm not getting any title; just the default "Title" value.
Question: Am I on the right track?
If so, what am I missing?
or... is there an alternative?
解决方案
整个问题归结为“多:1”范式。
我通过休息和散步得到了这个启示。
这就是众所周知的“方孔中的圆钉”场景。
我需要的是一个轻度耦合的关系,其中不需要标题值的来源。
因此使用了通知范式。
标题视图的标题是接收者,因此我使用了.onReceive修饰符:
struct NYTHeaderView: View {
@State private var title: String = ""
var body: some View {
ZStack {
Color.yellow
Text(title).onReceive(NotificationCenter.default.publisher(for: .headerTitle)) {note in
title = note.object as? String ?? "New York Times"
}
}.frame(height: Header.navigationBarHeight)
}
}
推荐阅读
- php - Zend 1 php 如何获取助手并在课堂外执行它?
- html - 选择第二个 col_content
- yaml - 用于从 Artifact 存储库下载最新 Artifact 的 Yaml 脚本
- sql-server - 在计算实例数时如何选择所有行?
- python - 如何在python中处理原始字符串中的通配符
- mysql - MySQL_Retrieving 基于 max 和 min_date 的股票价格
- javascript - history.back 在 Karma 中的行为不符合预期
- javascript - 如何通过方法在动态创建的行中分配/传递数据 - Vue.js
- machine-learning - 为什么不能从宏精度和召回率计算宏 F1 度量?
- mongodb - mongodb 聚合唯一性和计数同时具有更高级别的平均值