实战需求
SwiftUI是个非常好入门的语言,那么如何区分菜鸟与高手呢?让我们通过下面的小任务来测试您的水平吧!测试需求很简单,我们有多个sheet分别显示不同内容,请问如何解决
菜鸟级别
为了在SwiftUI中以模态显示视图,可以使用sheet修饰符。如果给定条件为真,则以其最简单的形式显示工作表。
struct ContentView: View {
@State var presentSheet = false
var body: some View {
VStack {
Button("Show Settings") {
self.presentSheet = true
}
}.sheet(isPresented: $presentSheet) {
SettingsView()
}
}
}
在此示例中,sheet修改器应用于VStack。但是,它也可以直接应用于Button。
但是,如果我们想从一个特定的视图显示多个View怎么办?
最合乎逻辑的选择是将另一个View修改器放置在现有的下面,因为我们可以随意链接修改器。不幸的是,这不起作用。为了使我们能够使用多个View,必须将每个修饰符直接应用于按钮。在SwiftUI中,无法使用两个或多个连续的工作表修改器,只有最后一个工作表修改器可以应用并且可以使用。结果,我们可以这样设计视图
@State var showSettingsView = false
@State var showProfileView = false
var body: some View {
VStack {
Button("Show Settings") {
self.showSettingsView = true
}.sheet(isPresented: $showSettingsView) {
SettingsView()
}
Button("Show Profile") {
self.showProfileView = true
}.sheet(isPresented: $showProfileView) {
ProfileView()
}
}
}
但是,正如您可以想象的那样,在运行的应用程序中,这种视图不会那么紧凑。如果您需要处理多个不同的工作表,则代码很快就会崩溃。此外,每个工作表都需要显示自己的@State。
为了避免大量的Views,如果有一种方法可以将这种导航逻辑从我们的View中分离到一个专用文件中,那就太好了。有不同的替代方法可以简化对多个View修改器的处理。
中级level
将表示逻辑移动到可观察的ViewModel中
首先,我们将把显示View的逻辑分离到单独的视图模型中。
class SheetNavigator: ObservableObject {
@Published var showSettingsView = false
@Published var showProfileView = false
}
该SheetNavigator类必须遵守ObservableObject协议,并且视图本身将使用@ObservedObject属性包装器对其进行观察。
@ObservedObject var sheetNavigator = SheetNavigator()
var body: some View {
VStack {
Button("Show Settings") {
self.sheetNavigator.showSettingsView = true
}.sheet(isPresented: self.$sheetNavigator.showSettingsView) {
SettingsView()
}
Button("Show Profile") {
self.sheetNavigator.showProfileView = true
}.sheet(isPresented: self.$sheetNavigator.showProfileView) {
ProfileView()
}
}
}
在将表示状态变量移动到视图模型之后,代码并没有真正改善。状态处理不可扩展,并且我们仍然有多个工作表修饰符使视图混乱。首先,将其减少为一个工作表修改器。
VStack {
Button("Show Settings") {
self.sheetNavigator.showSettingsView = true
}
Button("Show Profile") {
self.sheetNavigator.showProfileView = true
}
}.sheet(isPresented: ???) {
???
}
此时,我们只有一个工作表修改器,但是应该显示哪个视图以及将工作表绑定到哪个状态变量?答案是我们的SheetNavigator。