我一直在努力让我的tableview正确加载.count。我必须找到一种方法来告诉tableview只在我的图像和后期数组完全填充后才加载。
否则我会继续得到
fatal error: Array index out of range
在
cell.cellImage?.image = imagesArray[indexPath.row]
里面
cellForRowAtIndexPath
输出:
NUMBER OF POSTS->0
NUMBER OF IMAGES->0
NUMBER OF POSTS->0
NUMBER OF IMAGES->0
NUMBER OF POSTS->0
NUMBER OF IMAGES->0
POSTSARRAY COUNT->1
POSTSARRAY COUNT->2
POSTSARRAY COUNT->3
POSTSARRAY COUNT->4
NUMBER OF POSTS->4
NUMBER OF IMAGES->0
IMAGESARRAY COUNT->1
IMAGESARRAY COUNT->2
IMAGESARRAY COUNT->3
IMAGESARRAY COUNT->4
NUMBER OF POSTS->4
NUMBER OF IMAGES->4
代码
override func viewDidLoad() {
super.viewDidLoad()
// myTableView.estimatedRowHeight = 312.0
// myTableView.rowHeight = UITableViewAutomaticDimension
var query = PFQuery(className: "Post")
query.whereKey("hobbieTag", equalTo:"\(selectedHobbie)")
query.orderByAscending("description")
query.findObjectsInBackgroundWithBlock
{
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil
{
// println("HOBBIES.COUNT->\(hobbies?.count)")
for post in objects!
{
//GET POST TITLE
self.posts.append(post["postText"] as! String)
println("POSTSARRAY COUNT->\(self.posts.count)")
//TEST IMAGE
//var appendImage = UIImage(named: "logoPDF")
//self.imagesArray.append(appendImage!)
//GET IMAGE FILE
let postImageFile = post["postImage"] as? PFFile
postImageFile?.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in
var image = UIImage(data: imageData!)
self.imagesArray.append(image!)
println("IMAGESARRAY COUNT->\(self.imagesArray.count)")
}, progressBlock: { (progress: Int32) -> Void in
// println("PROGRESS->\(progress)")
})
}
self.myTableView.reloadData()
}
else
{
println(error?.localizedDescription)
println(error?.code)
}
// self.myTableView.reloadData()
}//END query
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(animated: Bool) {
myTableView.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
println("NUMBER OF POSTS->\(posts.count)")
println("NUMBER OF IMAGES->\(imagesArray.count)")
return posts.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! HobbieFeedTableViewCell
cell.cellTitle.text = posts[indexPath.row]
cell.cellSubtitle.text = posts[indexPath.row]
// cell.cellImage.image = UIImage(named: "logoPDF")
//cell.cellImage?.image = imagesArray[indexPath.row]
return cell
}
更新了代码
var query = PFQuery(className: "HobbieFeed")
query.whereKey("hobbieTag", equalTo:"\(selectedHobbie)")
query.orderByAscending("description")
query.findObjectsInBackgroundWithBlock
{
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil
{
let semaphore = dispatch_semaphore_create(0)
// println("HOBBIES.COUNT->\(hobbies?.count)")
for post in objects!
{
//GET POST TITLE
self.posts.append(post["postText"] as! String)
println("POSTSARRAY COUNT->\(self.posts.count)")
//TEST IMAGE
//var appendImage = UIImage(named: "logoPDF")
//self.imagesArray.append(appendImage!)
//GET IMAGE FILE
let postImageFile = post["postImage"] as? PFFile
postImageFile?.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in
var image = UIImage(data: imageData!)
self.imagesArray.append(image!)
println("IMAGESARRAY COUNT->\(self.imagesArray.count)")
dispatch_semaphore_signal(semaphore)
}, progressBlock: { (progress: Int32) -> Void in
println("PROGRESS->\(progress)")
})
}
// Wait for all image loading tasks to complete
for post in objects! {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
println("SHAPHORE POSTS COUNT->\(self.posts.count)")
println("SEMAPHORE IMAGES COUNT->\(self.imagesArray.count)")
}
self.myTableView.reloadData()
}
}//END query
答案 0 :(得分:4)
您在循环中在背景中加载图像,并在循环后立即调用reloadData
。但是,此时后台任务尚未完成。
for post in objects! {
...
// This starts a background operation
postImageFile?.getDataInBackgroundWithBlock(...)
...
}
// The background tasks are not necessarily completed at this point
self.myTableView.reloadData()
要等到所有后台任务完成,您才能使用信号量。这是一个基本的例子。
// Create a new semaphore with a value of 0
let semaphore = dispatch_semaphore_create(0)
// Kick off a bunch of background tasks
for i in 0...10 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
sleep(1) // Do some work or sleep
// Signal the semaphore when the task is done. This increments
// the semaphore.
dispatch_semaphore_signal(semaphore)
}
}
// Wait until all background tasks are done
for i in 0...10 {
// This waits until the semaphore has a positive value
// and then decrements it
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
}
// This is only executed after all background tasks are done
println("all tasks are done")
请注意,使用调度组可以简化此示例。但是,由于您使用完成处理程序调用函数而不是直接在队列上执行块,因此这不是您的选项。
将上述方法应用于您的代码将如下所示。
let semaphore = dispatch_semaphore_create(0) // Create a semaphore (value: 0)
for post in objects! {
...
postImageFile?.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in
... // Do your work
// Increment the semaphore when the image loading is completed
dispatch_semaphore_signal(semaphore)
}, progressBlock: {
...
})
...
}
// Wait for all image loading tasks to complete
for post in objects! {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
}
// This is only called after all images have loaded
self.myTableView.reloadData()
答案 1 :(得分:1)
嗨,据我所知,你做的正确,在后台异步加载数据。我认为它失败的地方是在你重新加载表的异步块中。在那里试试这个代码:
dispatch_async(dispatch_get_main_queue()){self.myTableView.reloadData()}
该块实际上是在不同的线程中运行,因此它与您的其他代码完全不同步。如果您正在使用测试,那么正确测试异步块也是一个问题。在这里,您可以使用waitForExpectationsWithTimeout(秒)来正确测试代码
答案 2 :(得分:0)
最后解决了这个问题。可能对其他用户有帮助,所以会在这里发布答案。
采用不同的方法,我相信更简单。
查询在视图上加载时发生,但在该阶段没有单独的图像或内容数组。单元格获取整个查询对象数组,然后检索每行所需的内容。如果有图像也更容易检测。
全球阵列:
var timelineData = NSMutableArray()
查看了加载查询:
var query = PFQuery(className: "Feed")
query.whereKey("Tag", equalTo:"\(selected)")
query.orderByAscending("description")
query.findObjectsInBackgroundWithBlock
{
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil
{
for object in objects!
{
self.timelineData.addObject(object)
}
self.myTableView.reloadData()
}
}//END query
tableview cellforrow
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//Cell identifiers
let standardCellIdentifier = "StandardCell"
let imageCellIdentifier = "ImageCell"
//get object, text and votes
let object = self.timelineData.objectAtIndex(indexPath.row) as! PFObject
var myText = object.objectForKey("postText") as? String
var hasImage = object.objectForKey("hasImage") as? Bool
var myVotes = object.objectForKey("votes") as! Int
let imageFromParse = object.objectForKey("postImage") as? PFFile
//if image
if hasImage == true
{
let imageCell = tableView.dequeueReusableCellWithIdentifier(imageCellIdentifier, forIndexPath: indexPath) as! FeedImageTVCell
//set image for cell
imageFromParse!.getDataInBackgroundWithBlock({ (imageData:NSData?, error:NSError?) -> Void in
if error == nil {
if let myImageData = imageData {
let image = UIImage(data:myImageData)
imageCell.cellImage!.image = image
}
}
}, progressBlock: { (percent: Int32) -> Void in
})
imageCell.cellVotes.text = "Votes - \(myVotes)"
imageCell.cellText.text = myText
return imageCell
}
//if no image
else
{
let standardCell = tableView.dequeueReusableCellWithIdentifier(standardCellIdentifier, forIndexPath: indexPath) as! FeedStandardTVCell
standardCell.cellVotes.text = "Votes - \(myVotes)"
standardCell.cellText.text = myText
return standardCell
}
}