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

时间:2020-01-26 16:31:23

标签: 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的私有功能中使用:

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

1 个答案:

答案 0 :(得分:0)

您需要创建一个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
            }
        }
}