如何将 parse-read 图像与 iOS 中的屏幕显示同步
How to synchronize a parse-read image with screen display in iOS
在 TableViewController 中,我显示 table 从解析数据库读取的记录。每个单元格显示缩略图、标题和注释。当一行被选中时,行索引被保存,并启动一个 segue 到 detailView Controller,它显示保存在全局 UIImage 变量 (noteImage) 中的图像。在 prepareForSegue 中,我在后台调用 loadImageFromParse,它读取与缩略图关联的图像并将其保存到 noteImage 中。
我的问题是从解析中读取图像有轻微延迟,因此 detailViewController 显示空白。当我从 detailViewController 返回到 TableViewController 并重新选择显示图片的行时。
我需要一种方法来保持 segue 调用,直到从 Parse 读取图像。
如有任何帮助,我们将不胜感激。
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath.row
self.performSegueWithIdentifier("NoteSegue", sender: self)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "NoteSegue"{
let vc = segue.destinationViewController as NoteViewController
vc.selectedRow = selectedRow
self.loadImageFromParse(objectIds[selectedRow])
}
}
// Load one image from parse
func loadImageFromParse (objectId: String) {
var query = PFQuery(className:"Record")
query.whereKey("objectId", equalTo:objectId)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
println("Successfully retrieved \(objects.count) records.")
for object in objects {
let userImageFile = object["image"] as PFFile!
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
noteImage = UIImage(data:imageData)!
println("Image successfully retrieved")
}
}
}
} else {
NSLog("Error: %@ %@", error, error.userInfo!)
}
}
}
我通过在启动后台方法 loadImageFromParse 之后和在 performSegueWithDelay 中启动 segue 之前引入 1 秒的延迟来解决问题。这会在 I select 行之后和图像在目标 segue 中可见之前稍作停顿,但它确保图像可用。显然,根据我从 Parse.com 获取的文件大小以及网络负载,这可能并不总是有效。如果图像尚未加载,我正在考虑向用户发出警报。
代码如下:
func performSegueWithDelay(timer: NSTimer) {
// action function for timer in didSelectRowAtIndexPath
self.performSegueWithIdentifier("NoteSegue", sender: self)
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath.row
self.loadImageFromParse(objectIds[selectedRow])
let myTimer : NSTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self,
selector: Selector("performSegueWithDelay:"), userInfo: nil, repeats: false)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "NoteSegue"{
let vc = segue.destinationViewController as NoteViewController
}
}
// Load one image from parse
func loadImageFromParse (objectId: String) {
var query = PFQuery(className:"Record")
query.whereKey("objectId", equalTo:objectId)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
println("Successfully retrieved \(objects.count) records.")
for object in objects {
let userImageFile = object["image"] as PFFile!
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
noteImage = UIImage(data:imageData)!
println("Image successfully retrieved")
}
}
}
} else {
NSLog("Error: %@ %@", error, error.userInfo!)
}
}
}
你说:
I need a way to hold the segue invocation till the image has been read from Parse.
也就是说,正如我想您现在已经猜到的那样,这并不是最好的方法。最好开始过渡到下一个场景,如果图像不可用,则显示 UIActivityIndicatorView
(微调器),检索图像,完成后,移除微调器并显示图像。但是延迟一段固定的时间并不会奏效:有时你会让用户等待的时间比需要的时间长;有时您不会等待足够长的时间。 (当然,同步执行请求总是不正确的方法。)
如果将此图像检索代码放在目标视图控制器中,则可能会简化此实现。让一个视图控制器启动异步过程并通知另一个视图控制器完成是很尴尬的(尽管可以通过明智地使用通知来完成)。但是在这个例子中(在你 select 一行之前你不知道要检索哪个图像),我看不出有什么好处。
综上所述,代码发起了两个异步请求,一个用于 Record
,一个用于图像本身。我想知道当您填充此初始 table 视图时是否可以捕获此 Record
信息。这样你只需要检索图像。现在也许 Parse 做了一些缓存并且 Record
的检索无论如何都非常快(因此在重构代码之前对其进行基准测试),但如果没有,您可能希望在填充时捕获 PFFile
对象原始 table 视图,使您不必进行两次查询。
在 TableViewController 中,我显示 table 从解析数据库读取的记录。每个单元格显示缩略图、标题和注释。当一行被选中时,行索引被保存,并启动一个 segue 到 detailView Controller,它显示保存在全局 UIImage 变量 (noteImage) 中的图像。在 prepareForSegue 中,我在后台调用 loadImageFromParse,它读取与缩略图关联的图像并将其保存到 noteImage 中。
我的问题是从解析中读取图像有轻微延迟,因此 detailViewController 显示空白。当我从 detailViewController 返回到 TableViewController 并重新选择显示图片的行时。
我需要一种方法来保持 segue 调用,直到从 Parse 读取图像。
如有任何帮助,我们将不胜感激。
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath.row
self.performSegueWithIdentifier("NoteSegue", sender: self)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "NoteSegue"{
let vc = segue.destinationViewController as NoteViewController
vc.selectedRow = selectedRow
self.loadImageFromParse(objectIds[selectedRow])
}
}
// Load one image from parse
func loadImageFromParse (objectId: String) {
var query = PFQuery(className:"Record")
query.whereKey("objectId", equalTo:objectId)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
println("Successfully retrieved \(objects.count) records.")
for object in objects {
let userImageFile = object["image"] as PFFile!
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
noteImage = UIImage(data:imageData)!
println("Image successfully retrieved")
}
}
}
} else {
NSLog("Error: %@ %@", error, error.userInfo!)
}
}
}
我通过在启动后台方法 loadImageFromParse 之后和在 performSegueWithDelay 中启动 segue 之前引入 1 秒的延迟来解决问题。这会在 I select 行之后和图像在目标 segue 中可见之前稍作停顿,但它确保图像可用。显然,根据我从 Parse.com 获取的文件大小以及网络负载,这可能并不总是有效。如果图像尚未加载,我正在考虑向用户发出警报。
代码如下:
func performSegueWithDelay(timer: NSTimer) {
// action function for timer in didSelectRowAtIndexPath
self.performSegueWithIdentifier("NoteSegue", sender: self)
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath.row
self.loadImageFromParse(objectIds[selectedRow])
let myTimer : NSTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self,
selector: Selector("performSegueWithDelay:"), userInfo: nil, repeats: false)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "NoteSegue"{
let vc = segue.destinationViewController as NoteViewController
}
}
// Load one image from parse
func loadImageFromParse (objectId: String) {
var query = PFQuery(className:"Record")
query.whereKey("objectId", equalTo:objectId)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
println("Successfully retrieved \(objects.count) records.")
for object in objects {
let userImageFile = object["image"] as PFFile!
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
noteImage = UIImage(data:imageData)!
println("Image successfully retrieved")
}
}
}
} else {
NSLog("Error: %@ %@", error, error.userInfo!)
}
}
}
你说:
I need a way to hold the segue invocation till the image has been read from Parse.
也就是说,正如我想您现在已经猜到的那样,这并不是最好的方法。最好开始过渡到下一个场景,如果图像不可用,则显示 UIActivityIndicatorView
(微调器),检索图像,完成后,移除微调器并显示图像。但是延迟一段固定的时间并不会奏效:有时你会让用户等待的时间比需要的时间长;有时您不会等待足够长的时间。 (当然,同步执行请求总是不正确的方法。)
如果将此图像检索代码放在目标视图控制器中,则可能会简化此实现。让一个视图控制器启动异步过程并通知另一个视图控制器完成是很尴尬的(尽管可以通过明智地使用通知来完成)。但是在这个例子中(在你 select 一行之前你不知道要检索哪个图像),我看不出有什么好处。
综上所述,代码发起了两个异步请求,一个用于 Record
,一个用于图像本身。我想知道当您填充此初始 table 视图时是否可以捕获此 Record
信息。这样你只需要检索图像。现在也许 Parse 做了一些缓存并且 Record
的检索无论如何都非常快(因此在重构代码之前对其进行基准测试),但如果没有,您可能希望在填充时捕获 PFFile
对象原始 table 视图,使您不必进行两次查询。