Reputation: 11427
There is several objects in SwiftUI 2 like Scene
and WindowGroup
as some sort of Scene.
After reading documentation and looking WWDC2020 video related to scenes I see hierarchy by the following way :
Single App => One or multiple scenes => Hierarchy of Views (or a few)
Each scene contains the root view of a view hierarchy and has a life cycle managed by the system. Each scene can be displayed with different ways depends to the platform.
WindowGroup
scene - how it's choosing the way to display them? ( vertically / horizontally )? And how to control it manually?I'm not sure that this is controlled with
HStack
andVStack
because of in my test project I got different result instead expected by some reason.
How I can control Scene
displayed? As example app have 2 scenes - each WindowGroup
with 2 Views in it. How can I switch from one scene to another in the same window of macOS?
How to open second scene in new window using SwiftUI?
Why do we need WindowGroup
at all? Isn't it a just a set of Views?
How to work with them in general?
Or where I can read more details than written in documentation or WWDC 1 min video (from 2.00 to 3.05) as there is not enough information to understand the topic.
Upvotes: 16
Views: 6889
Reputation: 11427
@SceneBuilder var body: some Scene {
WindowGroup {
NavigatorView()
}
}
enum DisplayedScene {
case Browser
case Status(url: URL)
}
struct NavigatorView: View {
@State var displayedScene = DisplayedScene.Browser
var body: some View {
VStack {
switch(model.displayedScene) {
case DisplayedScene.Browser:
BrowserView(model: browserViewModel, wndId: id)
case DisplayedScene.Status(let url):
VStack {
StatusView(url: url, wndId: id)
Button("back") { AppCore.signals.send(signal: Signal.TaoGit.Navigator.ShowBrowser(wndId: id) ) }
}
default:
Text("ERROR")
}
}.transition(.identity)
.animation(.easeInOut)
}
}
so all you need to change view displayed is to send signal to change displayedScene
.
Another way is to do displayedScene as EnvironmentVariable
. But in this case you will be able to work with ONLY ONE INSTANCE of window correctly. So this is a bad way. But can be OK for someone.
handlesExternalEvents
. Sample:import SwiftUI
@main
struct TestAppApp: App {
var body: some Scene {
WindowGroup {
MainView()
}
.handlesExternalEvents(matching: Set(arrayLiteral: Wnd.mainView.rawValue))
WindowGroup {
HelperView()
}
.handlesExternalEvents(matching: Set(arrayLiteral: Wnd.helperView.rawValue))
}
}
extension TestAppApp {
struct MainView: View {
@Environment(\.openURL) var openURL
var body: some View {
VStack {
Button("Open Main View") {
Wnd.mainView.open()
}
Button("Open Other View") {
Wnd.helperView.open()
}
}
.padding(150)
}
}
struct HelperView: View {
var body: some View {
HStack {
Text("This is ") + Text("Helper View!").bold()
}
.padding(150)
}
}
}
enum Wnd: String, CaseIterable {
case mainView = "MainView"
case helperView = "OtherView"
func open(){
if let url = URL(string: "taotao://\(self.rawValue)") {
print("opening \(self.rawValue)")
NSWorkspace.shared.open(url)
}
}
}
Why do we need WindowGroup at all? Isn't it a just a set of Views? -- It's telling to swiftUI that exactly this view can be shown as separated Window.
How to work with them in general? -- only with lot of hacks. Looks like SwiftUI is works really bad with MacOS.
Upvotes: 4