Reputation: 1155
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
.
However, I also have a UISearchBar
that searches for users and when it has results, should return AddFriendCell
s and reload the table.
Instead, I get this:
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
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
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