SwiftUI:在执行下面的代码之前等待 Alamofire 请求完成

标签 swift alamofire swiftui

我在函数中使用 Alamofire 请求从数据库中检索用户。问题是,请求所使用的函数取决于请求,因为我将结果作为 User 类的对象返回。

目前,它总是返回在我的函数顶部声明的默认 nil 值,因为请求下面的代码不会费心等待请求完成。 .success 或 .failure 部分中的基本打印语句证明了这一点(因为它不打印任何内容)。

我就是不知道怎么解决。我在网上查了一段时间,并且:

  • 要么我在论坛上遇到有关使用哪些类的建议,甚至懒得解释如何使用它
  • 或者我看到一个视频解释了完全不同的事情,例如处理多个请求

我可以向你们寻求帮助吗?我将在下面发布代码:

用户类别:

public class User
{

private var _name : String

public var Naam : String
{
    get {return self._name}
    set
    {
        /*
           Just a function from a static class which trims a string. It's not really relevant to my problem …
         */
        let name : String? = StringOps.trimString(string: newValue)

        if name == nil
        {
            fatalError()
        }

        self._name = newValue
    }
}

/*
 * And some fields and properties for:
 *  - firstname
 *  - username
 *  - password
 *  - email
 * They are basically equivalent to the one above
 */

// And a constructor
init(id : Int)
{
    self._id = id
    self._name = ""
    self._firstname = ""
    self._username = ""
    self._email = ""
    self._password = ""
}
}

LoginViewController 中的登录函数内的请求:

public func login(username: String, password: String)
    -> User?
var user : User? = nil

/* Some code that is trimming and checking the input.
   The username parameter gets put into a let parameter userName and the same goes for the password parameter. It's Ommitted here.
 */

let parameters : Parameters = [
        "userName" : userName!,
        "passWord" : passWord!
    ]

// _loginUrl is a private let String parameter
Alamofire.request(_loginUrl, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: nil)
    .responseJSON
    {
        (response : DataResponse<Any>) in
         switch (response.result)
        {
            case .success(_):
                let data: NSDictionary = (response.value as! NSArray)[0] as! NSDictionary

                /* The part commented out isn't working anyways,
                   and before I started changing the return type of my
                   function (was a Bool at first),
                   it worked well enough without it */
                /*
                if response.result.value != nil
                {
                    /* Convert the JSON to a User object */
                    let data = (response.value as! NSArray)[0] as! NSDictionary
                    user = User(id: data["id"] as! Int)
                    user!.Email = data["e_mail"] as! String
                    user!.Username = data["username"] as! String
                    user!.Name = data["name"] as! String
                    user!.Firstname = data["firstname"] as! String
                    user!.Password = data["password"] as! String
                }
                */

                user = User(id: data["id"] as! Int)
                user!.Email = data["e_mail"] as! String
                user!.Username = data["username"] as! String
                user!.Name = data["name"] as! String
                user!.Firstname = data["firstname"] as! String
                user!.Password = data["password"] as! String
            break

            case .failure(_):
                print(response.result.error as Any)

                // _error is also a private var member of LoginViewController
                self._error = "Something's wrong with your login credentials!"
                user = nil
            break
        }
    }

    return user
}

此函数在我的 LoginView 中的私有(private)函数中使用:

struct LoginView
    : View
{
    // Some unimportant bits

    private func logIn()
    {
        // username and password are @State private vars which are bound to their corresponding Text()
        let user : User? = self.controller.login(username: self.username, wachtwoord: self.password)
        // other code
    }
}

最佳答案

您需要创建一个completionHandler

当您的代码获取对 User 对象的引用时,仍然是 nil,因为服务器的响应尚未到来。

public func login(用户名:字符串,密码:字符串) -> 用户?

将其更改为:

public func login(用户名:字符串,密码:字符串,完成:@escaping (User?) -> Void)

然后你可以这样做:

private func logIn() {

    self.controller.login(username: self.username, wachtwoord: self.password) { user in 
                guard let user = user else {
                print("Error while retrieving user")
                return
                }
           /// Access your user here
            }
        }
}

关于SwiftUI:在执行下面的代码之前等待 Alamofire 请求完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59920354/

相关文章:

iOS Swift 检测图像旋转

swift - 在 HTTP POST 请求中传递多个参数

json - 将 json 集合响应映射到 swift 对象类的简单方法

ios - UITableView使用下载图片时不流畅

swift - 从 SwiftUI 的 List 中删除列表元素

swift - 使用 MVVM 模式登录 Facebook

ios - secureTextEntry 不隐藏我的 UITextView 的文本

ios - 在关键帧动画 Swift 期间更改不透明度

swiftui - 点击 NavigationLink 后如何执行操作?

swift - 结构数组未在 View 中更新