异步设置变量并在视图控制器中使用

时间:2015-03-19 01:18:14

标签: swift asynchronous parse-platform pfobject

我们说我有以下异步查询:

var kittens: [PFObject]!

self.tempView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "pushToView"))

var query = PFQuery(className: "Kittens")
query.findObjectsInBackgroundWithBlock({ (objects, error) in
    if let kittenObjects = objects as? [PFObject] {
        self.kittens = kittenObjects
    }
})

我有一个提供视图控制器的方法:

func pushToView() {
    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let viewController: KittensViewController = mainStoryboard.instantiateViewControllerWithIdentifier("kittensViewController") as! KittensViewController
    viewController.kittens = self.kittens
    self.presentViewController(viewController, animated: true, completion: nil)
}

因为我在异步查询块中设置了self.kittens,所以当我尝试在呈现的视图控制器中访问self.kittens时,它显然不起作用(它是' s总是空的。)

获得这样的工作的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

有几种选择。主要的是您需要在查询完成时更新KittensViewController

  • 在视图控制器中创建KittensViewController一个包含小猫数组的属性。查询完成后,您不仅会更新self.kittens,还会更新self.kittensViewController.kittens = kittenObjects。这不是最好的设计,但应该有效。

  • 更好的设计是将查询放在一个自己的控制器类中,在完成后触发NSNotification。然后,当新的小猫到达并更新您的视图时,您可以在代码的任何位置收听。

Query会抛出通知

    var query = PFQuery(className: "Kittens")
    query.findObjectsInBackgroundWithBlock({ (objects, error) in
        if let kittenObjects = objects as? [PFObject] {
             dispatch_async(dispatch_get_main_queue()) {
                 NSNotificationCenter.defaultCenter().postNotificationName("KittensQueryDidFinish", object:kittenObjects, userInfo:dataDict))
        }
    })

ViewController注册通知并更新其模型

viewDidLoad添加以下内容:

NSNotificationCenter.defaultCenter().addObserverForName("KittensQueryDidFinish", object: nil, queue: NSOperationQueue.mainQueue) { note in
     let kittens = note.object
     [weak self].kittens = kittens
}

使用该方法,您可以随时随地获得更新。现在,您必须在已经加载小猫时解决问题。因此,我建议您引入一个共享控制器对象(也就是单例)来执行查询并存储小猫。然后你可以从任何地方访问小猫。

答案 1 :(得分:1)

如果var kittens: [PFObject]!是您的viewController的属性,我认为实现您想要的最简单的方法就是这样声明:

var kittens: [PFObject]! {
        didSet {
            dispatch_async(dispatch_get_main_queue(), { [weak self] in
                if let strongSelf = self {
                    strongSelf.pushToView()
                }
            })
        }

因此,每次设置小猫时,它都会执行pushToView()功能。你必须改变这一行:

self.tempView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "pushToView"))

执行查询而不是pushToView()。例如:

self.tempView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "performFetch"))

当然,您需要创建函数:

func performFetch() {
  var query = PFQuery(className: "Kittens")
  query.findObjectsInBackgroundWithBlock({ (objects, error) in
      //should be created weak self to avoid retain cycles
      if let kittenObjects = objects as? [PFObject] {
          self.kittens = kittenObjects
      }
  })
}

但如果小猫不是属性,则可以创建performFetch()函数,更改手势识别器并在使用self.pushToView()设置小猫后添加dispatch_async dispatch_get_main_queue()(如didSet因为你需要更新主队列中的UI。