Reputation: 73
I have a problem with UITableView
inserting, deleting rows.
I'm trying to do a "Facebook messenger" seen effect in a UITableView
. I have many cells that each indicates a message, and between them, there is a many cells that each indicates people who have seen this message so far. All of those data are stored in correctly.
Now, I want that when I receive a seen notification to delete a seen cell from the table and then insert another one at the proper index depending on my data source (in most cases last item). And when a user sends a message I'm adding his message to the table then removing his last seen cell, then reinsert another one after his message.
Now debugging the logic every thing is OK with updating data source and requesting to insert, delete on the UITableView
, but I still get:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (36) must be equal to the number of rows contained in that section before the update (36), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
I' have tried to put the call to this logic inside a beginUpdates();
and endUpdates();
. All insertion, deleting is called inside main thread (UI)
Any help would be appreciated, many thanks.
Edit
here is my code:
//// Insert a seen status for user, handles seen logic
private func insertSeen(event: UEvent?) -> (removed: Int, inserted: Int) {
// Make a holder for insertion result
var result: (removed: Int, inserted: Int) = (removed: -1, inserted: -1);
// Check if no event was given
if(event == nil){
return result; }
if(event?.creatorID == "" && self.type == .single && self.participants.count > 0){
event?.creatorID = self.participants[0].ID
event?.creatorName = self.participants[0].username;
}
// Get last seen for targeted user
let lastSeen = lastSeenForUser(id: (event?.creatorID)!);
// Get targeted participant
var particiapnt = self.participant(id: event!.creatorID);
// If sender is self -> he will not be found in particiapnts list
// So, we should get it's data from UserData
if(event?.creatorID == UserData.current.ID){
particiapnt = UserData.current;
}
// Check if no event was given
if(particiapnt == nil){
return result; }
let name = particiapnt?.username;
var image = particiapnt?.photo;
if(image != nil) { image = image?.Scale(Width: 20); }
// Store number of events before updates -> usefull to tell if seen has created a new event
let count: Int = self.events.count;
// Check if user has just sent a seen status
if((count > 0 && lastSeen == count - 1) || particiapnt == nil){
// Return a no insertion result [-1,-1]
return result;
}
if(delegate != nil){
delegate.beginUpdates();
}
// Check if user hasn't sent any seen event before
if(lastSeen < 0){
// Check if last event in group is seen
if(self.events.count > 0 && self.events.last?.type == .seen) {
// Add participant to last event
let _ = self.events.last?.addParticipant(id: (event?.creatorID)!, name: name!, image: image);
// Return where this user seen event was added
result = (removed: lastSeen, inserted: self.events.count - 1);
// Check delegate isn't null -> can apply changes
if(delegate != nil){
// Tell delegate about the update
self.delegate.updateEvent(at: result.inserted, event: self.events[result.inserted]);
}
} else {
// If last event is'nt seen -> Create a new one
// Get a basic event
let seen = BasicEvent;
// Set event type as seen
seen?.type = .seen;
// Get where this participant was added
let _ = seen?.addParticipant(id: (event?.creatorID)!, name: name!, image: image);
// Insert the new craeted seen event to events
self.events.append(seen!);
// Return where this user seen event was added
result = (removed: lastSeen, inserted: self.events.count - 1);
// Check delegate isn't null -> can apply changes
if(delegate != nil){
// Tell delegate about the update
self.delegate.addEvent(at: result.inserted, event: event, animation: .fade);
}
}
}
// Handle user has sent a seen event before
else {
// Get where the targeted user has sent his last seen status
let seen = self.events[lastSeen];
// Remove targeted user from his last seen status event
let _ = seen.removeParticipant(id: (event?.creatorID)!);
// If seen is'nt empty yet -> jus t remov current participant
if(seen.participants.count > 0){
// Return where this user seen event was added
result = (removed: lastSeen, inserted: self.events.count - 1);
// Check delegate isn't null -> can apply changes
if(delegate != nil){
// Tell delegate about the update
self.delegate.updateEvent(at: result.removed, event: self.events[result.inserted]);
}
} else {
// Delete empty seen event
self.events.remove(at: lastSeen);
// Return where this user seen event was added
result = (removed: lastSeen, inserted: self.events.count - 1);
// Check delegate isn't null -> can apply changes
if(delegate != nil){
print("coount: \(delegate.getTableView().numberOfRows(inSection: 0)) | 2 ");
// Tell delegate about the update
self.delegate.deleteEvent(at: result.removed, event: self.events[result.removed]);
}
}
// Check if last event in group is seen
if(self.events.count > 0 && self.events.last?.type == .seen) {
// Add participant to last event
let _ = self.events.last?.addParticipant(id: (event?.creatorID)!, name: name!, image: image);
// Return where this user seen event was added
result = (removed: lastSeen, inserted: self.events.count - 1);
// Check delegate isn't null -> can apply changes
if(delegate != nil){
// Tell delegate about the update
self.delegate.updateEvent(at: result.inserted, event: self.events[result.inserted]);
}
} else {
// Get a basic event
let seen = BasicEvent;
// Set event type as seen
seen?.type = .seen;
// Get where this participant was added
let _ = seen?.addParticipant(id: (event?.creatorID)!, name: name!, image: image);
// Insert the new craeted seen event to events
self.events.append(seen!);
// Return where this user seen event was added
result = (removed: lastSeen, inserted: self.events.count - 1)
// Check delegate isn't null -> can apply changes
if(delegate != nil){
// Tell delegate about the update
self.delegate.addEvent(at: result.inserted, event: seen, animation: .fade);
}
}
}
if(delegate != nil){
delegate.endUpdates();
}
// Return final result of this insertion
return result;
}
Upvotes: 0
Views: 428
Reputation: 98
Debug your numberOfRowsInSection
method,
it's still returning 36 even though you inserted 1 row in UITable
Upvotes: 0
Reputation: 139
Debug it, might be you missed to update you datasource while update the table view.
Upvotes: 0