Eric Johnson
Eric Johnson

Reputation: 1155

Different UITableViewCells overlapping

I have a UITableView with 3 prototype cells and 3 custom cell classes: FriendCell FriendRequestCell and AddFriendCell.

Initialized, the table displays Friends.

If there are any FriendRequests, it displays them in the section above Friends.

If there are no FriendRequests, it only displays Friends.

enter image description here

However, I also have a UISearchBar that searches for users and when it has results, should return AddFriendCells and reload the table.

Instead, I get this:

enter image description here

Code:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    if searching == true {
        if let cell = tableView.dequeueReusableCellWithIdentifier("AddFriendCell", forIndexPath: indexPath) as? AddFriendCell {
            let resultCell = userResults[indexPath.row]
            cell.configureCell(resultCell)
        }
    } else {
        if friendRequests.isEmpty ||  (indexPath.section == 1)  {
            if let cell = tableView.dequeueReusableCellWithIdentifier("FriendCell", forIndexPath: indexPath) as? FriendCell {
                let friendCell = friends[indexPath.row]
                cell.configureCell(friendCell)
            }
        } else {
            if (indexPath.section == 0) {
                if let cell = tableView.dequeueReusableCellWithIdentifier("FriendRequestCell", forIndexPath: indexPath) as? FriendRequestCell {
                    let friendRequestCell = friendRequests[indexPath.row]
                    cell.configureCell(friendRequestCell)
                }
            }
        }
    }
    return FriendCell()
}


func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    if searching == true {
        return 1
    } else {
        return friendsDataSource.count
    }
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if searching == true {
        return userResults.count
    } else {
        return friendsDataSource[section].count
    }
}

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    if searching == true {
        return nil
    } else {
        if friendsDataSource.count > 1 {
            if section == 0 {
                return "Friend Requests"
            } else if section == 1 {
                return "Friends"
            }
        } else {
             return "Friends"
        }
        return "Friends"
    }
}

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if searching == true {
        return 0
    } else {
        return 25
    }
}

func searchBarSearchButtonClicked(searchBar: UISearchBar) {
    searching = true
    searchBar.resignFirstResponder()
    userResults = [UserProfile]()
    activitySpinner.startAnimating()

    if let searchText = searchBar.text {
        let userProfileQuery = PFQuery(className: "UserProfile")
        userProfileQuery.whereKey("username", containsString: searchText)

        userProfileQuery.findObjectsInBackgroundWithBlock({ resultArray, error in
            if error != nil {
                print("there's been an error searching for users: \(error)")

            } else if let resultArray = resultArray {
                print("number of results: \(resultArray.count)")
                self.parseResults = resultArray

                for userProfile in resultArray {
                    let username = userProfile["username"] as! String
                    let profilePicUrl = userProfile["profilePicUrl"] as! String
                    let parseObjectId = userProfile.objectId!

                    let newProfile = UserProfile(username: username, profilePicUrl: profilePicUrl, parseObjectId: parseObjectId)
                    self.userResults.append(newProfile)
                }
                self.tableView.reloadData()
                self.activitySpinner.stopAnimating()
            }
        })
    }
}

Any ideas on the root of the problem?

Upvotes: 0

Views: 349

Answers (2)

Nicolas Miari
Nicolas Miari

Reputation: 16246

OK, here is the code for multiple types of cell:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    if searching == true {

        let cell = tableView.dequeueReusableCellWithIdentifier("AddFriendCell", forIndexPath: indexPath) as! AddFriendCell

        // ...configure your cell...

        return cell 
    } 
    else{
        if friendRequests.isEmpty ||  (indexPath.section == 1)  {

            let cell = tableView.dequeueReusableCellWithIdentifier("FriendCell", forIndexPath: indexPath) as! FriendCell

            // ...configure your cell...

            return cell            
        } 
        else{
            if (indexPath.section == 0) {

                let cell = tableView.dequeueReusableCellWithIdentifier("FriendRequestCell", forIndexPath: indexPath) as! FriendRequestCell

                 // ...configure your cell...

                return cell
            }
            else {
                // Decide what to do if section is NOT 0. If this CAN happen
                // and you don't have a cell type to return, it is a design flaw.
                // don't add a adummy "return FriendCell()" as a fallback for a
                // case that should never happen, to make the compiler happy. 
                // This type of error should be caught during development.
            }
        }
    }
}

(See the comment paragraph on how to deal with the unsuported execution path)

Alternatively, you could declare cell as a var of type UITableViewCell outside of all if/else blocks, assign it to the appropriatey dequeued cell inside, (i.e., remove the let keyword if modifying the code above), and return it at the very end.

But you still need to make sure it is initialized before returning.

Upvotes: 1

rose
rose

Reputation: 241

if the method findObjectsInBackgroundWithBlock is asynchronous, I think you can use self.tableView.reloadData() instead of dispatch_async(dispatch_get_main_queue(), { self.tableView.reloadData() }) add self.tableView.rowHeight = 50

and you don't return your addfriendcell. you just return FriendsCell() at the last line. add the return cell.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    if searching == true {
        if let cell = tableView.dequeueReusableCellWithIdentifier("AddFriendCell", forIndexPath: indexPath) as? AddFriendCell {
            let resultCell = userResults[indexPath.row]
            cell.configureCell(resultCell)
            return cell! //add the return
        }
    } else {
        if friendRequests.isEmpty ||  (indexPath.section == 1)  {
            if let cell = tableView.dequeueReusableCellWithIdentifier("FriendCell", forIndexPath: indexPath) as? FriendCell {
                let friendCell = friends[indexPath.row]
                cell.configureCell(friendCell)
                return cell! //add the return
            }
        } else {
            if (indexPath.section == 0) {
                if let cell = tableView.dequeueReusableCellWithIdentifier("FriendRequestCell", forIndexPath: indexPath) as? FriendRequestCell {
                    let friendRequestCell = friendRequests[indexPath.row]
                    cell.configureCell(friendRequestCell)
                    return cell! //add the return
                }
            }
        }
    }
    return FriendCell()
}

Upvotes: 1

Related Questions