1

假设我有以下异步查询:

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

让这样的事情发挥作用的最佳方法是什么?

4

2 回答 2

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

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

于 2015-03-22T16:38:13.930 回答
1

有几个选项。最主要的是您需要KittensViewController在查询完成时进行更新。

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

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

查询抛出通知

    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
}

使用这种方法,您可以在任何需要的地方获得更新。现在你必须在小猫已经被加载的情况下解决这个问题。因此,我建议您引入一个共享控制器对象(又名单例)来执行查询并存储小猫。然后你可以从任何地方访问小猫。

于 2015-03-22T14:08:08.857 回答