提问者:小点点

在SwiftUI中使用外部函数内部绑定


我目前正在学习SwiftUI,想开发自己的应用程序。我设计了一个loginview和一个loginhandler,它们应该处理登录背后的所有逻辑。当用户输入错误的用户名/密码时,屏幕上应该会出现一个警报。我用状态变量loginerror解决了这个问题。但现在出现了棘手的部分,因为我想将这个变量的绑定传递给loginhandler中的登录函数。看一下下面的代码:


import SwiftUI

struct LoginView: View
{
    @EnvironmentObject var loginHandler: LoginHandler
    
    @State private var username: String = ""
    @State private var password: String = ""
    @State private var loginError: Bool = false
    
    ...
    
    private func login()
    {
        loginHandler.login(username: username, password: password, error: $loginError)
    }
}

我现在正在尝试更改登录函数中的错误值:

import Foundation
import SwiftUI

class LoginHandler: ObservableObject
{
    public func login(username: String, password: String, error: Binding<Bool>)
    {
        error = true
    }
}

但我发现了错误

无法赋值:“error”是“let”常量

我认为这是有意义的,因为你不能在Swift中编辑参数。我还尝试过_error=true,因为我曾经看到下划线与绑定结合使用,但这也不起作用。

但后来我想到了一个工作解决方案:error.wrappedvalue=true。我唯一的问题是苹果开发人员文档中的以下语句:

此属性提供对值的数据的主要访问。但是,您不直接访问wrappedValue。取而代之的是,使用与@binding属性一起创建的property变量。

虽然我超级高兴它起作用了,但我想知道有没有更好的办法来解决这种情况呢?


共2个答案

匿名用户

你也可以更新一个函数的参数,这里是一个例子,这不是使用绑定或状态,它是inout!

我现在正在尝试更改登录函数中的错误值:

无法赋值:“error”是“let”常量

所以用这个方法或例子你可以!

struct ContentView: View {
    
    @State private var value: String = "Hello World!"
    
    var body: some View {
        
        Text(value)
            .padding()
        
        Button("update") {
            
            testFuction(value: &value)
        }
        
    }
}


func testFuction(value: inout String) {
    
    value += " updated!"
}

匿名用户

我知道你想做什么,但它会在后面引起问题,因为你在这里处理的是状态。现在一个解决办法是:

  • 您可以将错误抽象到类中,但这样就会将用户名密码放在一个位置,而将错误放在另一个位置。

理想的解决方案是在同一地点把它全部抽象化。从您的视图中删除所有属性,并将其设置为如下所示:

   import SwiftUI

struct LoginView: View
{
    @EnvironmentObject var loginHandler: LoginHandler
    

   
   // login() <-- Call this when needed
    ...
    
    
}

那么在你的课堂上:

    import Foundation
    import SwiftUI
    
  @Published error: Bool = false
   var username = ""
   var password = ""

    class LoginHandler: ObservableObject
    {
        
       

       public func login()    {
           //If you can't login then throw your error here
           self.error = true
   }
    }

您唯一要做的是更新username和password`,例如,您可以通过以下操作来完成

TextField("username", text: $loginHandler.username)
TextField("username", text: $loginHandler.password)