致命错误:数组索引超出范围。刷新时迅速

Posted

技术标签:

【中文标题】致命错误:数组索引超出范围。刷新时迅速【英文标题】:fatal error: Array index out of range. Swift when refresh 【发布时间】:2016-02-13 07:25:20 【问题描述】:

尝试了很多次以找出导致致命错误的原因。但是,还是想不通。当我尝试使用拉取刷新表时,第一个表(结果表)会导致此错误。第二个表(favoriteProductTableView)完美运行,所以我没有写任何关于第二个的代码。想知道为什么。感谢您的帮助。

    var followArray = [String]()
    var resultsNameArray = [String]()
    var resultsImageFiles = [PFFile?]()
    var resultsDetailsArray = [String]()
    var resultsDetailsImageFiles = [PFFile?]()
    var resultsObjectID = [String]()
    var resultsTitle = [String]()
    var personPriceArray = [String]()
    var personQuantityArray = [String]()
    var personOrderTypeArray = [String]()

    var refresher:UIRefreshControl!

    override func viewDidLoad() 
        super.viewDidLoad()
        favoriteProductTableView.hidden = true
        refresher = UIRefreshControl()
        refresher.tintColor = UIColor.blackColor()
        refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
        self.resultsTable.addSubview(refresher)
    

    override func viewDidAppear(animated: Bool) 
        refreshResults()
    

    func refresh()
        refreshResults()
    

    func refreshResults()
        switch(segmentedControl.selectedSegmentIndex)
        case 0:
            followArray.removeAll(keepCapacity: false)
            resultsNameArray.removeAll(keepCapacity: false)
            resultsImageFiles.removeAll(keepCapacity: false)
            resultsDetailsArray.removeAll(keepCapacity: false)
            resultsDetailsImageFiles.removeAll(keepCapacity: false)
            resultsObjectID.removeAll(keepCapacity: false)
            resultsTitle.removeAll(keepCapacity: false)
            personPriceArray.removeAll(keepCapacity: false)
            personQuantityArray.removeAll(keepCapacity: false)
            personOrderTypeArray.removeAll(keepCapacity: false)

            let followQuery = PFQuery(className: "follow")
            followQuery.whereKey("user", equalTo: (PFUser.currentUser()!.username)!)
            followQuery.whereKey("userToFollow", notEqualTo: (PFUser.currentUser()!.username)!)

            followQuery.findObjectsInBackgroundWithBlock  (objects:[PFObject]?, error: NSError?) -> Void in
                if error != nil 
                
                for object in objects! 
                    self.followArray.append(object.objectForKey("userToFollow") as! String)
                
                let query = PFQuery(className: "products")
                query.whereKey("userName", containedIn: self.followArray)

                query.findObjectsInBackgroundWithBlock  (catchobjects:[PFObject]?, error:NSError?) -> Void in
                    if error != nil 
                    
                    for catchobject in catchobjects! 
                        if catchobject.objectForKey("selling_price") != nil 
                            self.personPriceArray.append(catchobject.objectForKey("selling_price") as! String)
                            self.personOrderTypeArray.append("Selling")
                         else 
                            self.personPriceArray.append(catchobject.objectForKey("buying_price") as! String)
                            self.personOrderTypeArray.append("Buying")
                        
                        self.personQuantityArray.append(catchobject.objectForKey("quantity") as! String)
                        self.resultsNameArray.append(catchobject.objectForKey("unique_username") as! String)
                        self.resultsImageFiles.append(catchobject.objectForKey("profile_picture") as? PFFile)
                        self.resultsDetailsArray.append(catchobject.objectForKey("details") as! String)
                        self.resultsDetailsImageFiles.append(catchobject.objectForKey("detailsImage") as? PFFile)
                        self.resultsTitle.append(catchobject.objectForKey("title") as! String)
                        self.resultsObjectID.append(catchobject.objectId!)
                    
                    dispatch_async(dispatch_get_main_queue()) 
                        self.resultsTable.reloadData()
                    
                    self.loadEmptyLabel(self.resultsTable)
                
                self.refresher.endRefreshing()
            
            break
        case 1:
            ...
            break
        default:
            break
        
    

    func loadEmptyLabel(tableView: UITableView) 
        let emptyLabel = UILabel(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height))
        emptyLabel.textAlignment = NSTextAlignment.Center
        emptyLabel.textColor = UIColor.blackColor()
        emptyLabel.text = "No matched result found."
        tableView.backgroundView = emptyLabel
        tableView.separatorStyle = UITableViewCellSeparatorStyle.None
        var resultCount = Int()
        if tableView == resultsTable 
            resultCount = resultsNameArray.count
         else 
            resultCount = resultsTitleArray.count
        
        if resultCount == 0 
            tableView.reloadData()
            emptyLabel.hidden = false
         else 
            emptyLabel.hidden = true
        
    

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        var numRow: Int = 0
        switch(segmentedControl.selectedSegmentIndex)
        case 0:
            numRow = resultsNameArray.count
            break
        case 1:
            numRow = resultsTitleArray.count
            break
        default:
            break
        
        return numRow
    

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
        if tableView == resultsTable 
            let cell:favoritedTableViewCell = resultsTable.dequeueReusableCellWithIdentifier("Cell") as! favoritedTableViewCell
            cell.profileLbl.text = self.resultsNameArray[indexPath.row]
            cell.messageTxt.text = self.resultsDetailsArray[indexPath.row]
            cell.priceLabel.text = "\(self.personOrderTypeArray[indexPath.row]) \(self.personQuantityArray[indexPath.row]) for $\(self.personPriceArray[indexPath.row])"
            cell.titleLabel.text = self.resultsTitle[indexPath.row]
            if resultsImageFiles[indexPath.row] != nil 
                resultsImageFiles[indexPath.row]!.getDataInBackgroundWithBlock  (imageData:NSData?, error:NSError?) -> Void in
                    if error == nil
                        let image = UIImage(data: imageData!)
                        cell.imgView.image = image
                    
                
             else 
                cell.imgView.image = UIImage(named: "Profile Picture")
            
            if resultsDetailsImageFiles[indexPath.row] != nil
                resultsDetailsImageFiles[indexPath.row]?.getDataInBackgroundWithBlock( (imageData:NSData?, error:NSError?) -> Void in
                    if error == nil
                        let image = UIImage(data: imageData!)
                        cell.detailsImg.image = image
                    
                )
             else 
                cell.detailsImg.image = UIImage(named: "Profile Picture")
            
            return cell
         else 
        ....
        
    

【问题讨论】:

在挖掘你的代码之前,你能把范围缩小到相关的代码吗?大多数情况下,您可以通过这种方式找出错误。告诉我们错误在哪里也很好;) 对不起。我试过了,但上面的代码都与导致错误的表视图有关。我猜代码看起来很乱的原因是我在表格视图中使用了 10 个数组。 您至少可以告诉我们错误在哪里;) 【参考方案1】:

您的numberOfRowsInSection 函数根据segmentedControl.selectedSegmentIndex 返回两个数组长度之一,而cellForRowAtIndexPath 根据正在显示的tableView 索引数组。这看起来不正确,特别是考虑到您的引用 `` 似乎没有在任何地方填充 - 它应该只是 resultsTitle?。

另外,您正在从后台线程调用self.resultsTable.reloadData()。这很糟糕 - 它必须从主线程调用:

dispatch_async(dispatch_get_main_queue()) 
    self.resultsTable.reloadData()

尽管如此,你也不清楚为什么你在循环中也有这个。

【讨论】:

刚刚更新了 dispatch_async。但是,如果 cellForRowAtIndexPath 基于正在显示的 tableView 索引数组,那么我不应该使用 segmentedControl.selectedSegmentIndex?我应该使用什么?我应该使用类似 if tableView == result table return resultsNameArray.count resultsTitleArray 是第二个表格视图中的另一个数组。

以上是关于致命错误:数组索引超出范围。刷新时迅速的主要内容,如果未能解决你的问题,请参考以下文章

使用致命错误刷新tableview时应用程序崩溃:索引超出范围Swift3

Swift 致命错误:数组索引超出范围

Swift 致命错误:数组索引超出范围

致命错误:追加数组时数组索引超出范围

SwiftUI - 致命错误:从数组中删除元素时索引超出范围

致命错误:在Swift中访问10个元素的数组时,数组索引超出范围