异步设置变量并在视图控制器中使用
Set variable asynchronously and use within view controller
假设我有以下异步查询:
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
时显然不起作用(它始终为空)。
让这样的东西发挥作用的最佳方法是什么?
有几个选项。最主要的是您需要在查询完成时更新 KittensViewController
。
在保存小猫数组的视图控制器中将 KittensViewController
设为 属性。查询完成后,您不仅会更新 self.kittens
,还会更新 self.kittensViewController.kittens = kittenObjects
。这不是最佳设计,但应该可以。
更好的设计是在自己的控制器中进行查询 class,在完成时触发 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
}
通过这种方法,您可以随时随地获得更新。现在你必须在小猫已经加载时解决问题。因此,我建议您引入一个共享控制器对象(又名单例)来执行查询并存储小猫。然后你可以从任何地方访问小猫。
如果 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()
函数,更改手势识别器并在使用 dispatch_async dispatch_get_main_queue()
设置 kittens 后添加 self.pushToView()
(如在 didSet
) 中,因为您需要更新主队列中的 UI。
假设我有以下异步查询:
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
时显然不起作用(它始终为空)。
让这样的东西发挥作用的最佳方法是什么?
有几个选项。最主要的是您需要在查询完成时更新 KittensViewController
。
在保存小猫数组的视图控制器中将
KittensViewController
设为 属性。查询完成后,您不仅会更新self.kittens
,还会更新self.kittensViewController.kittens = kittenObjects
。这不是最佳设计,但应该可以。更好的设计是在自己的控制器中进行查询 class,在完成时触发 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
}
通过这种方法,您可以随时随地获得更新。现在你必须在小猫已经加载时解决问题。因此,我建议您引入一个共享控制器对象(又名单例)来执行查询并存储小猫。然后你可以从任何地方访问小猫。
如果 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()
函数,更改手势识别器并在使用 dispatch_async dispatch_get_main_queue()
设置 kittens 后添加 self.pushToView()
(如在 didSet
) 中,因为您需要更新主队列中的 UI。