首页 > 解决方案 > SwiftUI:在执行以下代码之前等待 Alamofire 请求完成

问题描述

我在函数中使用 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 中的私有函数中使用:

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
    }
}

标签: swiftalamofireswiftui

解决方案


你需要创建一个completionHandler

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

public func login(username: String, password: String) -> User?

将其更改为:

public func login(username: String, password: String, completion: @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
            }
        }
}

推荐阅读