Swift:SwiftUI 视图的多个条件的内联评估

Posted

技术标签:

【中文标题】Swift:SwiftUI 视图的多个条件的内联评估【英文标题】:Swift: Inline evaluation of multiple conditions for SwiftUI View 【发布时间】:2020-05-16 12:56:38 【问题描述】:

在 SwiftUI 中,要根据条件修改 View,我们可以使用三元运算符,因此允许两种情况。但是,如果我想评估多个条件,我该怎么办,使它更像 switch(多个案例)而不是 if/else(两个案例)? 为了演示,Text 视图可以像这样使用三元运算符由 @State var isLoggedIn: Bool 修改:

Text(self.isLoggedIn ? "Welcome!" : "Please log in")

如果我现在想添加更多案例,会做的是使用一个函数,但这会使代码比简单优雅的三元运算符要长得多:

struct ContentView: View 

    enum Status 
        case loggedIn, loggedOut, expired
    

    @State var userStatus: Status

    func displayMessage(status: Status) -> some View 
        switch(status) 
        case .loggedIn:
            return Text("Welcome!")
        case .loggedOut:
            return Text("Please log in")
        case .expired:
            return Text("Session expired")
        
    

    var body: some View 
        displayMessage(status: userStatus)
        // more views
    

那么有人对我如何简化和缩短第二个代码有任何建议吗?

【问题讨论】:

【参考方案1】:

当涉及到使用 switch 作为枚举值来实现 SwiftUI 视图时,您当前的解决方案是最常见的代码。我会坚持使用这个版本,即使它有点冗长。

话虽如此,为了缩短它,如果你将它包装在一个 Group 中,你可以使用 switch inline 而不使用单独的 func:

struct SwiftUISwitchView: View 

    @State var userStatus: Status = .loggedIn

    var body: some View 
        VStack 
            Group  () -> Text in
                switch(self.userStatus) 
                case .loggedIn:
                    return Text("Welcome!")
                case .loggedOut:
                    return Text("Please log in")
                case .expired:
                    return Text("Session expired")
                
            
        
    

这是一个方便的概述问题,总结了在 SwiftUI 视图中使用 switch 的选项:Using switch/enums in SwiftUI Views

【讨论】:

【参考方案2】:

这是可能的方法

struct ContentView: View 

    enum Status: String 
        case loggedIn  = "Welcome!"
        case loggedOut = "Please log in"
        case expired   = "Session expired"
    

    @State var userStatus: Status = .loggedOut

    var body: some View 
        Text(userStatus.rawValue)

        // more views
    

【讨论】:

感谢您的回复。虽然,我有点打算在多个地方使用userStatus 来更改不同的视图(文本、图像等),那么有没有适合这种情况的解决方案?例如,如果我不仅想要一条消息,而且还显示登录状态的图像怎么办? 您的意思是您希望displayMessage 根据userStatus 返回不同的视图? @qitianshi 或者你的意思是你想用userStatus 来确定其他视图的外观? @Sweeper 后者:也使用userStatus 来确定其他视图的外观【参考方案3】:

您不需要返回Text,您可以只返回String

func displayMessage(status: Status) -> String 
    switch(status) 
    case .loggedIn:
        return "Welcome!"
    case .loggedOut:
        return "Please log in"
    case .expired:
        return "Session expired"
    


var body: some View 
    Text(displayMessage(status: userStatus))
    // more views

这会稍微缩短您的代码。为了进一步缩短它,您可以使用字典:

func displayMessage(status: Status) -> String 
    [Status.loggedIn: "Welcome",
     .loggedOut: "Please log in",
     .expired: "Session expired"][status]!

编辑:

如果您需要userStatus 来确定另一个视图的外观,您可以编写另一个返回相应值的方法。


如果你非常喜欢三元运算符,确实可以链式:

Text(
    userStatus == .loggedIn ? 
        "Welcome" : (userStatus == .loggedOut ? "Please log in" : "Session expired")
)

我不会推荐这个。它不是很可读。但这确实更“内联”。

【讨论】:

【参考方案4】:

您所描述的内容在 SwiftUI 中仅使用三元运算符即可实现 - 请参阅此处的描述:https://www.programiz.com/swift-programming/ternary-conditional-operator

最终会变成这样:

Text(self.isLoggedIn ? "Welcome!" : self.isNotLoggedIn ? "not welcome" : "who are you" )

您可以在每个 : 和 ? 之间添加尽可能多的额外条件如您所见。 所以,上面的例子对应(带有伪代码):

if self.isLoggedIn 
  "Welcome"

else if self.isNotLoggedIn 
  "not welcome"

else 
"who are you"

【讨论】:

以上是关于Swift:SwiftUI 视图的多个条件的内联评估的主要内容,如果未能解决你的问题,请参考以下文章

通过 Swift 泛型初始化 SwiftUI 视图

将多个子视图传递给 SwiftUI 中的视图

如何在 SwiftUI 中启动应用程序时有条件地加载视图?

SwiftUI 更改内联 navigationBarTitleDisplayMode 的导航栏背景颜色

Swift和SwiftUI

SWIFTUI:在视图中导航并返回