从远程加载后在 segue 上传递数据

Pass data on segue after loading from remote

我有带有此代码的控制器:

var adItem: JSON!
var item: JSON? {
    didSet {
        self.loadAdData()
    }
}

func loadAdData() {
    let url = "\(Config.apiAdsUrl)\(item!)/"
    Alamofire.request(.GET, url).responseJSON { (request, response, json, error) in
        if (json != nil) {
            var jsonObj = JSON(json!)
            self.adItem = jsonObj
        }
    }
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "imagesSegue" {
        let infoIC = segue.destinationViewController as AdImagesViewController
        infoIC.adItem = self.adItem // this line pass nil value to controller, but i need to pass that JSON data
    }
}

我想获取数据并将其传递给 segue 视图控制器。

我无法在 AdImagesViewController 中获取该 adItem,当我打印它时,我总是得到 nil,因为 prepareForSegue 在启动时触发,所以 loadAdData 需要一些时间从远程获取数据..

有解决办法吗?

如果您想在有数据的情况下进行 segue,您可以让一个单独的单例对象处理提取。该控制器和您选择的控制器都可以访问该对象。每当 JSON 改变时,对象可以通知控制器刷新新数据。

您也可以等到数据已获取后调用 performSegue,但是如果用户的服务很低或根本没有服务怎么办?但如果这是您想要的,您可以创建一个 shouldSegue 布尔变量并将其设置为 YES。在回调中,检查标志是否设置为 YES,如果是,则执行 segue。您也可以使用队列。 segue 是 UI 相关的,发生在主队列上,而 fetch 通常放在后台队列上,然后更新 UI。也许将获取放在主队列中? :-/

我正在构建一个登录页面,我遇到了类似的问题,但我找到了下一个代码的解决方案: 我用 dispatch_async 包装 performSegueWithIdentifier 以获取主队列,我配置 prepareForSegue 以将数据传递到我在 EventsVC 文件中创建的变量中。

import UIKit
import Alamofire

class ViewController: UIViewController {

    @IBOutlet weak var emailTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!

    var login: Int = 0
    var clientId: String = ""
    var email: String = ""
    // I'll send the data in this variable
    var userData = [String : AnyObject]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    }

    @IBAction func loginButton(sender: AnyObject) {

        if emailTextField.text != "" && passwordTextField.text != "" {

            userLogin(emailTextField.text!, userPassword: passwordTextField.text!)

        } else {
            let alert = UIAlertController(title: "Error", message: "Fields are required!", preferredStyle: .Alert)
            let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
            alert.addAction(action)
            self.presentViewController(alert, animated: true){}
        }
    }

    func userLogin(email: String, userPassword: String) {

        let userUrl = "\(URL_BASE)\(URL_KEY)User/login"
        let url = NSURL(string: userUrl)!

        let parameters = [
            "email" : email,
            "password" : userPassword
        ]

        Alamofire.request(.POST, url, parameters: parameters).responseJSON { response in

            if let data = response.result.value as? [String : AnyObject] {
                print("Response JSON: \(data)")

                self.userData = data

                if let isLogin = data["check"] as? Int {
                    self.login = isLogin
                }

                if let client = data["client_id"] as? String {
                    self.clientId = client
                }

                print(self.userData)

                if self.login == 1 {
                    // You need to wrap methods that call UI updates with dispatch_asynch to get the main queue
                    dispatch_async(dispatch_get_main_queue(), { () -> Void in
                        self.performSegueWithIdentifier("segueEventsVC", sender: self.userData)
                    })

                } else {
                    let alert = UIAlertController(title: "Error", message: "Your credentials are invalid!", preferredStyle: .Alert)
                    let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
                    alert.addAction(action)
                    self.presentViewController(alert, animated: true){}
                }
            }
        }
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "segueEventsVC" {
            if let eventsVC = segue.destinationViewController as? EventsVC {
                    eventsVC.userData = self.userData
            }
        }
    }
}