0

I am attempting to populate a table view with rows of friends. When I run the code, it sometimes works and sometimes doesn't. When it doesn't, it shows the following error:

fatal error: Array index out of range

The code for the class is here:

import UIKit
import Parse
import ParseUI

class ConnectionsViewController: PFQueryTableViewController  {

    var connectionObject = ConnectionClass()
    var userObject = UserClass()
    var friendsUsernamesListArray: [String] = []
    var friendsInfoListArray: [PFObject] = []


    func loadFriendsUsernames(completion: (result: [String]) -> Void)
    {
        print("1")

        let query = PFQuery(className:"FriendsConnections")

        query.whereKey("appUsername", equalTo:PFUser.currentUser()!["appUsername"])
        query.findObjectsInBackgroundWithBlock {
            (objects: [PFObject]?, error: NSError?) -> Void in

            if error == nil{
                self.friendsUsernamesListArray = objects![0]["friendsList"] as! NSArray as! [String]
                completion(result: self.friendsUsernamesListArray)


            }else{
                print(error)

            }

        }
    }

    func loadFriendsInfo()
    {
        print("2")
        let query : PFQuery = PFUser.query()!

        query.whereKey("appUsername", containedIn: self.friendsUsernamesListArray)
        query.findObjectsInBackgroundWithBlock {
            (objects: [PFObject]?, error: NSError?) -> Void in

            if error == nil{
                for item in objects! {
                    self.friendsInfoListArray.append(item)
                }
            }else{                
                print(error)
            }
        }
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        print("3")
    }

    override func queryForTable() -> PFQuery {
        print("4")
        self.loadFriendsUsernames({ (result)->Void in
            print("Inside Completion ")
            if(result.count > 0)
            {
                print("Completion - Array not empty")
                self.loadFriendsInfo()
            }else{
                print("Completion - Array empty")
            }

        })

        let query = PFQuery(className: "FriendsConnections")
        query.cachePolicy = .NetworkOnly
        query.orderByAscending("createdAt")
        return query
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
        print("5")
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! ConnectionTableCell

        //print("Array Content: \(friendsInfoListArray)")



        if(indexPath.row >= 0)
        {

            cell.connectionNameLabel.text = self.friendsInfoListArray[indexPath.row]["name"] as? String

        }else{
            print("Something going wrong populating the cell")
        }
        return cell
    }

    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        print("6")
        if indexPath.row + 1 > self.objects?.count
        {
            return 44
        }

        let height = super.tableView(tableView, heightForRowAtIndexPath: indexPath)
        return height
    }


    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        print("7")
        /*Get all data of friend clicked and pass to next view*/
        self.userObject.name = friendsInfoListArray[indexPath.row]["name"] as? String
        self.userObject.username = friendsInfoListArray[indexPath.row]["appUsername"] as? String
        self.userObject.email = friendsInfoListArray[indexPath.row]["email"] as? String
        self.userObject.mobile = friendsInfoListArray[indexPath.row]["mobile"] as? String


        let tempWorkAddress = friendsInfoListArray[indexPath.row]["workAddress"] as! NSArray as! [String]
        let tempHomeAddress = friendsInfoListArray[indexPath.row]["homeAddress"] as! NSArray as! [String]



        /*Handle addresses where empty*/
        if(tempHomeAddress.isEmpty || tempWorkAddress.isEmpty)
        {
            self.userObject.homeAddress.append("")
            self.userObject.homeAddress.append("")
            self.userObject.workAddress.append("")
            self.userObject.workAddress.append("")
        }else{
            self.userObject.homeAddress = friendsInfoListArray[indexPath.row]["homeAddress"] as! NSArray as! [String]
            self.userObject.workAddress = friendsInfoListArray[indexPath.row]["workAddress"] as! NSArray as! [String]

        }


        //to get the image file
        if let userImageFile = friendsInfoListArray[indexPath.row]["ProfilePic"] as? PFFile {
            userImageFile.getDataInBackgroundWithBlock {
                (imageData: NSData?, error: NSError?) -> Void in
                if error == nil {
                    if let imageData = imageData {
                        self.userObject.userProfilePic = UIImage(data:imageData)
                    }
                }else{
                    self.userObject.userProfilePic = nil
                    print(error)
                }
            }

        }else{
            self.userObject.userProfilePic = nil
        }


        self.performSegueWithIdentifier("showConnectionDetailsSegue", sender: self)

    }

    /*override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.friendsUsernamesListArray.count
    }*/

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
        print("8")
        if (segue.identifier == "showConnectionDetailsSegue") {
            // pass data to next view
            print(segue.description)
            let destinationVC = segue.destinationViewController as! FriendDetailViewController
            destinationVC.userObject = self.userObject;

        }
    }

}

The debugger when the execution fails highlight this line:

    cell.connectionNameLabel.text = self.friendsInfoListArray[indexPath.row]["name"] as? String

Now I added print statements with numbers to see the flow, and it is as following:

4
1
3
Inside Completion 
Completion - Array not empty
2
6
6
5
6
fatal error: Array index out of range

Any help will be appreciated since I am on this problem for couple of days without a solution.

8
  • What are you using for tableView(tableView, numberOfRowsInSection)? It's commented out... also your test if(indexPath.row >= 0) is meaningless, it should be if indexPath.row < self.friendsInfoListArray.count Commented Dec 24, 2015 at 9:52
  • @Grimxn I tried to change the if statement earlier and didn't work. It printed empty cells & triggered the else part. I also tried it now and still the same Commented Dec 24, 2015 at 9:56
  • Also, whenever friendsInfoListArray i.e. datasource is updated you should call reloadData on tableView Commented Dec 24, 2015 at 9:57
  • Please uncomment numberOfRowsInSection and use return self.friendsInfoListArray.count Commented Dec 24, 2015 at 10:06
  • @san the reason why I commented it out is that when I leave it in, nothing displays anymore in the table rows. Commented Dec 24, 2015 at 10:07

2 Answers 2

1

Look at this method

 override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell?

And start debugging, because you method trying to take item that is out of array.

Example:

var myArray = [0,1,2,3];
myArray[0] // 0

In your case:

var myArray = [0,1,2,3];
myArray[4] // Error!

Small help issue for you:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
        print("5")
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! ConnectionTableCell

        //print("Array Content: \(friendsInfoListArray)")

        if (self.friendsInfoListArray.count < indexPath.row) {
           print("PROBLEM")
        }

        if(indexPath.row >= 0)
        {

            cell.connectionNameLabel.text = self.friendsInfoListArray[indexPath.row]["name"] as? String

        }else{
            print("Something going wrong populating the cell")
        }
        return cell
    }
Sign up to request clarification or add additional context in comments.

6 Comments

Just to clarify the error is not happening there. Once the record load (when they load and not fail), I am able to transition data to detail view successfully via this method. The problem is triggered on line in method cellForRowAtIndexPath
@ksa_coder yap wrong method name sorry, try to print what index path you try to use and what is you're array count
print friendsInfoListArray.count and print indexPath.row and you will see
I tried that now and it shows: print("Index Path Row: (indexPath.row)") shows as 0 and print("Array Count: (friendsUsernamesListArray.count)") shows as 2
I added the check you added above...the problem statement is not printing even though execution failing for same reason
|
-1

in the number of sections method , you need to do this :

return array.count

thats it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.