指数0超越界限为空数组,有时工作,有时不 [英] index 0 beyond bounds for empty array, sometime works, sometime does not

查看:242
本文介绍了指数0超越界限为空数组,有时工作,有时不的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

MainTVC显示由parse.com检索PFObjects,如果我挖掘的tableView细胞之一,它会显示一个包含图片和文字信息的详细视图图片和帖子的标题中的tableView。 mainTVC使用prepareForSegue传递数据的DetailView。

MainTVC shows pictures and title of post in tableView by retrieving PFObjects from parse.com, if I tap one of the tableView Cell, it will show detail post view that contains pictures and texts. mainTVC pass data to detailView by using prepareForSegue.

多数时候,它运作良好,但是当我试图挖掘它的tableView显示图片之后或滚动我真快,我得到一个错误,尤其是当我用缓慢的互联网做到这一点。

Most of time, it is working well, but when I try tap it right after tableView shows picture or I scroll really fast, I get an error, especially when I do it with slow internet.

2015年10月22日14:36:52.501 BANY [2595:874380] *终止应用程序由于未捕获的异常'NSRangeException',原因是:'* - [__ NSArrayM objectAtIndex:]:索引0超越界限的空数组

2015-10-22 14:36:52.501 bany[2595:874380] * Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array’

2015年10月22日14:39:40.855 BANY [2600:875293] *终止应用程序由于未捕获的异常'NSRangeException',原因是:'* - [__ NSArrayM objectAtIndex:]:指数2超越界限的空数组

2015-10-22 14:39:40.855 bany[2600:875293] * Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 2 beyond bounds for empty array'

有时我得到的指数超出2为界限空数组,有时为零。

sometime I get index 2 beyond bounds for empty array, sometime zero.

我不认为我有一个空的indexPath。

I don't think that I have an empty indexPath.

我猜,我就可以检索数据已经完成之前挖掘。

I guess, I tap on it before retrieving data has been done.

这是我的MainTVC code

here is my MainTVC Code

import UIKit
import Parse

class MainTVC: UITableViewController {

@IBOutlet weak var categorySegment: UISegmentedControl!

var resultSearchController : UISearchController!



lazy var postsArray : NSMutableArray = NSMutableArray()
lazy var filterdArray : NSMutableArray = NSMutableArray()
var objectArray = [String]()
  var parentObjectID = String()

var objectTwo : PFObject!
   override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(true)

        //사이즈 조절

        //tableView.estimatedRowHeight = tableView.rowHeight
    //tableView.rowHeight = UITableViewAutomaticDimension


    bringAllDatafromParse()
}


@IBAction func segmentTapped(sender: AnyObject) {




    postsArray = []



    switch categorySegment.selectedSegmentIndex {
    case 0 :
        bringAllDatafromParse()
    case 1 :
        bringCategoryDataFromParse(1)

    case 2 :
        bringCategoryDataFromParse(2)

    case 3 :
        bringCategoryDataFromParse(3)

    default :
        bringAllDatafromParse()



    }
    self.tableView.reloadData()

        }


    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return postsArray.count


}





    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
           let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MainTVCE





       var postObjects = self.postsArray.objectAtIndex(indexPath.row) as! PFObject




    cell.didRequestToShowComment = { (cell) in
        let indexPath = tableView.indexPathForCell(cell)
        let objectToSend = self.postsArray[indexPath!.row] as? PFObject
        // Show your Comment view controller here, and set object to send here
        self.objectTwo = objectToSend!
        self.performSegueWithIdentifier("mainToComment", sender: self)


    }
    cell.soldLabel.hidden = true

    if (postObjects.objectForKey("sold") as! Bool) == true {
        cell.soldLabel.hidden = false

    }

            //제목

    cell.titleLabel.text = postObjects.objectForKey("titleText") as! String

            // 닉네임

    if let nickNameExists = postObjects.objectForKey("nickName") as? String {
        cell.nickNameLabel.text = nickNameExists
    }else {
        cell.nickNameLabel.text = postObjects.objectForKey("username") as? String
    }



    //시간
    let dateFormatter:NSDateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "MM /dd /yy"
    cell.timeLabel.text = (dateFormatter.stringFromDate(postObjects.createdAt!))



            // 가격

    let price = (postObjects.objectForKey("priceText") as! String)
            cell.priceLable.text = "   $\(price)"



               // 이미지
    let mainImages = postObjects.objectForKey("front_image") as! PFFile


    mainImages.getDataInBackgroundWithBlock { (imageData, error) -> Void in
        let image = UIImage(data: imageData!)
        cell.mainPhoto.image = image
    }

    // 프로필
    if let profileImages = (postObjects.objectForKey("profile_picture") as? PFFile){
                profileImages.getDataInBackgroundWithBlock { (imageData, error) -> Void in
                    let image = UIImage(data: imageData!)
                    cell.profilePhoto.image = image

        }

    }else{ cell.profilePhoto.image = UIImage(named: "AvatarPlaceholder")
    }
    circularImage(cell.profilePhoto)

    return cell
}


    // MARK: - Animate Table View Cell

//    override func tableView(tableView: UITableView, willDisplayCell                cell:   UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
//        cell.alpha = 0
        //        UIView.animateWithDuration(0.5) { () -> Void in
        //          //            cell.alpha = 1
//        }
//    }
//


func bringAllDatafromParse() {
    //activityIndicatorOn()

    postsArray = []
    let query = PFQuery(className: "Posts")

    query.orderByAscending("createdAt")
    query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error) -> Void in
        if error == nil && objects != nil{

            for object : PFObject in objects! {

                self.postsArray.addObject(object)

            }

            let array : Array = self.postsArray.reverseObjectEnumerator().allObjects


            self.postsArray = array as! NSMutableArray


        }
     self.tableView.reloadData()

        }

}





func bringCategoryDataFromParse(category : Int) {



    let query = PFQuery(className: "Posts")
     query.whereKey("category", equalTo: category)
    query.orderByAscending("createdAt")
    query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error) -> Void in
        if error == nil && objects != nil{

            for object : PFObject in objects! {

                self.postsArray.addObject(object)

            }

            let array : Array = self.postsArray.reverseObjectEnumerator().allObjects


            self.postsArray = array as! NSMutableArray
            self.tableView.reloadData()

        }


    }

}




 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

 if (segue.identifier == "mainToComment") {


let destViewController : CommentVC = segue.destinationViewController as! CommentVC

let selectedRowIndex = self.tableView.indexPathForSelectedRow

destViewController.object = objectTwo


}

if (segue.identifier == "mainToDetail") {


    let selectedRowIndex = self.tableView.indexPathForSelectedRow
            let destViewController : DetailVC = segue.destinationViewController as! DetailVC
            destViewController.object = (postsArray[(selectedRowIndex?.row)!] as? PFObject)


}

}

func circularImage(image : UIImageView) {
    image.layer.cornerRadius = image.frame.size.width / 2
    image.clipsToBounds  = true
    image.layer.borderColor  = UIColor.blackColor().CGColor
    image.layer.borderWidth = 1
}

}

我的问题是,

如果我的猜测是正确的,我应该怎么做我的code的等待,从解析检索数据?

If my guess is right, what should I do with my code for wait that retrieving data from parse?

如果不是这样,这是什么错误的原因是什么?我该如何解决?

If it is not, what is the reason of this error? and How can I fix it?

推荐答案

您可能会需要提供更多的code和细节,但两件事情浮现在脑海中。

You'll probably need to provide more code and details but two things come to mind.

首先,根据函数的名字,看来你要添加的东西到另一个背景队列中的数组,而试图重新present或与他们通过UI主队列交互(你的表视图)。我不知道是如何解析的作品,但一眼,我会确保你没有多个后台查询实例,同时与阵列玩。

First, according to the name of the function, it appears you're adding things to the array in another background queue while trying to represent or interact with them on the main queue via the UI (your table view). I'm not sure how Parse works but at a glance, I'd make sure you don't have multiple background query instances playing with your array at the same time.

二,这是我不清楚你是如何处理小区重用。难道你的细胞是努力使从他们被用来重新present另一行一previous时间使用信息,被重用过吗?也许你不能完全复位所有的状态。

Second, it's unclear to me how you're handling cell reuse. Could your cells be trying to make use of information from a previous time they were used to represent another row, before being reused? Maybe you're not fully resetting all state.

更新中的注释问题

展望解析(我从来没有用过),我看到你不太使用得当。 这个例子显示的(在Objective-C)如何你对 query.findObjectsInBackgroundWithBlock(...)调用的处理方式。这个例子似乎并没有表现出如何处理更新UI。

Looking into Parse (which I've never used), I see that you're not quite using it properly. This example shows (in Objective-C) how your call to query.findObjectsInBackgroundWithBlock(...) should be handled. The example doesn't appear to demonstrate how to handle updating your UI.

块的内容在后台中运行。谷歌可可UI线程安全,并读出尽你所能。它适用于更一般的线程安全问题为好。我认为每一个你的UI是创建表格单元格或与他们互动时,数组中存放不同的东西(这将影响到数)。你也做的背景下你的 postsArray 更换了很多,所有这一切将绊倒你的表视图,因为UI对象一般都不会被更新或操纵从任意但主队列/线程。

The contents of the block is being run in the background. Google "cocoa UI thread safety" and read as much as you can. It applies to more general thread safety issues as well. I think every time your UI is creating table cells or interacting with them, the array holds something different (which would affect count). You're also doing a lot of replacing of your postsArray in the background and all of this will "trip up" your table view, since UI objects generally cannot be updated or manipulated from any but the main queue/thread.

什么出现在你的情况要发生的是,查询在后台更改阵列,同时在用户界面(表视图/细胞等)试图更新。如果我告诉你剥每个这五个土豆和转储他们都出来的时候你还在脱皮第三土豆,当你达到进入(现在的空箱)第四马铃薯,它不存在,所以(哑土豆-peeling你是计算机程序),你不知道做什么,说:但有没有第四土豆(土豆[3] 越界 ),或者更糟糕,你抢和剥离的空气,或者你自己的手......你明白我的意思?

What appears to be happening in your case is that the queries are changing the array in the background at the same time the user interface (table view / cells, etc.) is trying to update. If I tell you "peel each of these five potatoes" and dump them all out when you're still peeling the third potato, when you reach into the (now empty bin) for the fourth potato, it's not there, so (dumb potato-peeling computer program that you are), you don't know what to do and say "but there's no fourth potato" ("potatoes[3] is out of bounds"), or worse, you grab and peel air, or your own hand... Do you see my point?

我的建议是看这个例子,你可以在网上找到的使用 findObjectsInBackgroundWithBlock对其他任何(...)来看看别人是怎么处理的UI更新。如果没有寻找到它自己很多,我觉得你的块的内容应的只有的手柄增加东西向可变数组的主线的,并要求表视图,以更新的。为此,也许一旦您确定完成查询,后台块中,跳回到主队列修改 postsArray 和更新,如表这样的:

My suggestion is to look at the example and any others you can find on the web for the use of findObjectsInBackgroundWithBlock(...) to see how others handle UI updating. Without looking into it much myself, I think the contents of your block should only handle adding things to the mutable array on the main thread and asking the table view to update. To that end, maybe once you're sure the query is complete, within the background block, "hop back to" the main queue to modify your postsArray and update the table like this:

// Inside the background block/closure, we've decided the query is complete,
// so we "hop to" the main thread to update our array and ask the UI to reflect it
dispatch_async(dispatch_get_main_queue()) { () -> Void in

    self.postsArray.appendContentsOf(objects!)
    self.tableView.reloadData()

}

这里的想法是,UI一定会做到无论从任何扰动它最后一次在我们的 dispatch_async派出块/关闭执行()呼叫的时间更新。这个小code块添加到主队列,这意味着它 - 也只有它 - 将是围绕运行的循环之旅期间执行。这样可以确保您的帖子阵列和随后的UI更新的任何变化都会发生的一起的(他们应该),只有的一次

The idea here is that the UI will definitely be done updating from whatever perturbed it last time by the time the dispatched block/closure in our dispatch_async() call is executed. This little block of code is added to the main queue, which means it - and only it - will be executed during that "trip around the run loop". This ensures any changes to your posts array and subsequent UI updates will happen in together (as they should) and only one at a time.

您应该应用此逻辑/方法的其他查询为好,因为每一个可能导致同样的问题。我希望这有助于。

You should apply this logic / approach to the other queries as well, since each is likely to cause the same problem. I hope this helps.

这篇关于指数0超越界限为空数组,有时工作,有时不的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆