如何在SwiftUI中全屏显示视图?

13
我在开发一个登录界面 view,现在我想在用户登录后显示该 view,但我不希望用户能够返回到登录的 view。 在UIkit中,我使用了present()方法,但是在SwiftUI中使用presentation(_ modal: Modal?)时,view没有占据整个屏幕,而Navigation也不是一个选项。
谢谢!

我认为苹果删除了函数演示(...)。 - David Kadlcek
4个回答

13

我不希望用户有返回登录界面的可能性。

如果是这样,您不应该将视图呈现移开登录页面,而应完全替换它。

您可以通过有条件地构建登录视图或“应用程序视图”来实现此目的。

类似于以下代码:

// create the full screen login view
struct LoginView: View {
    // ...
}

//create the full screen app veiw
struct AppView: View {
    // ...
}

// create the view that swaps between them
struct StartView: View {
    @EnvironmentObject var isLoggedIn: Bool // you might not want to use this specifically.

    var body: some View {
        isLoggedIn ? AppView() : LoginView()
    }
}

通过使用这样的模式,您不会呈现或导航离开登录视图,而是完全替换它,因此它不再在视图层次结构中。

这可以确保用户无法返回到登录屏幕。

同样地...通过像这样使用 @EnvironmentObject,您可以稍后编辑它(以退出登录),您的应用程序将自动返回到登录屏幕。


听起来很不错,但我还有一个问题:在LoginView的模型中,我从服务器获取了一些数据,我需要在AppView中使用这些数据,我该如何将这些数据传输到AppView? - Sorin Lica
@SorinLica,这就是EnvironmentObject的作用。我承认我还不太清楚如何完全使用EnvironmentObject,但它就是为此而存在的。例如,您可能希望将用户信息保存在其中。然后,任何使用EnvironmentObject的内容都可以访问该信息,并且当其发生变化时,视图将得到更新。请参阅此演讲... https://developer.apple.com/wwdc19/226 - Fogmeister
2
考虑到某些视图无法解析为类型,这是否可以编译? - Mike Pollard
2
耶,自从什么时候可以返回两种不同类型之一了...这会出错的。 - PhillipJacobs
1
我从编译器收到了“无法将类型为'AppView'的返回表达式转换为返回类型'some View'”的消息。 - los.adrian

6
struct ContentView: View {
    @EnvironmentObject var userAuth: UserAuth 
    var body: some View {
        if !userAuth.isLoggedin {
            return AnyView(LoginView())
        } else {
            return AnyView(HomeView())
        }
    }
}

1
你好,欢迎来到StackOverflow。发表答案固然不错,但更好的做法是解释它是如何解决问题的。 - WaLinke
请不要像这样使用AnyView,这是一种反模式。由于View的内容默认为ViewBuilder,因此您无需指定return语句或使用AnyView() - Wil Shipley

5
将正文封装在一个 Group 中,以消除编译器错误:
struct StartView: View {

@EnvironmentObject var userAuth: UserAuth

var body: some View {
    Group {
        if userAuth.isLoggedin {
            AppView()
        } else {
            LoginView()
        }

    }
}

0

我为自己制作了这个扩展。欢迎任何反馈/想法。:)

https://github.com/klemenkosir/SwiftUI-FullModal

使用方法

struct ContentView: View {

    @State var isPresented: Bool = false

    var body: some View {
        NavigationView {
            Button(action: {
                self.isPresented.toggle()
            }) {
                Text("Present")
            }
            .navigationBarTitle("Some title")
        }
        .present($isPresented, view: ModalView(isPresented: $isPresented))
    }
}

struct ModalView: View {

    @Binding var isPresented: Bool

    var body: some View {
        Button(action: {
            self.isPresented.toggle()
        }) {
            Text("Dismiss")
        }
    }
}

有什么办法可以在从 ModalView 返回 ContentView 后触发 onAppear 事件? - ytp92
嗯,这个有点难。现在不确定是否可能。您可以修改.present方法,添加一个可选的dismissed回调函数,每次呈现的屏幕被解除时都会调用它。 - Klemen Košir
我已经尝试使用.transition(.move)它可以工作,可以在视图之间触发诸如onAppear之类的事件,但似乎与NavigationView的可见性存在问题。 - ytp92

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接