After deleting a row, it is still showed.
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
Audio *current = [logic findAudioByRow:indexPath.row];
[logic deleteAudio:current callback:^{
dispatch_async(dispatch_get_main_queue(), ^{
//some audio player logic that does not important for the topic
});
}];
}
this method calls that function:
-(void)deleteAudio:(Audio *)audio callback:(voidCallback)callback
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSString * ownerId = [NSString stringWithFormat:#"%ld", [audio.owner_id integerValue]];
NSString * audioId = [NSString stringWithFormat:#"%ld", [audio.aid integerValue]];
APIData *apiData = [[APIData alloc] initWithMethod:DELETE_AUDIO_BY_ID user:[[UserLogic instance] currentUser] queue:requestQueue params:[[NSMutableDictionary alloc] initWithObjectsAndKeys:audioId,#"aid", ownerId, #"oid", nil]];
[APIRequest executeRequestWithData:apiData block:^(NSURLResponse *response, NSData *data, NSError *error) {
}];
callback();
[self updateContent:YES];
});
}
I don't understand when I should call reloadData to update view.
Can't see the delete method in your code. This is how you have to use the delete row methods.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
[mySourceArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
When you delete a row of table view also remove the related record from array, then after reload tableview.
Related
I started an iOS project and I'm working with UITableView to display a list of pilots with images . I did pagination on my api and I tried to load more once you scrolled the tableview. the problem that I got is that the new cells are always displayed on top of the tableview not in the bottom. Please check on my code if there is a solution I will be grateful
- (void)loadData :(NSInteger)page {
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
url = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#%#%ld",NSLocalizedString(#"get_pilots",nil),mainDelegate.idAccount,#"?page=",(long)page]];
task = [restObject GET:url :mainDelegate.token completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSMutableDictionary* jsonResponse = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:nil];
NSArray *pilotKey = [jsonResponse objectForKey:#"pilot"];
for (NSDictionary *pilotItem in pilotKey ){
PilotObject *pilotObj = [PilotObject new];
[pilotObj getPilot:pilotObj :pilotItem];
[_pilotsAll addObject:pilotObj];
}
dispatch_async(dispatch_get_main_queue(), ^{
[hud hideAnimated:YES];
[self checkTableView:_pilotsDisplay :self.view];
[viewPilots.tableViewPilots reloadData];
});
}];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (currentPage == totalPages) {
return [_pilotsDisplay count];
}
return [_pilotsDisplay count] + 1;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == [_pilotsDisplay count] - 1 && currentPage<totalPages ) {
[self loadData:++currentPage];
NSLog(#"current page : = %ld",(long)currentPage);
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == [_pilotsDisplay count]) {
static NSString *identifier = #"PilotCellTableViewCell";
PilotCellTableViewCell *cell = (PilotCellTableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
cell.hidden=YES;
UIActivityIndicatorView *activityIndicator = (UIActivityIndicatorView *)[cell.contentView viewWithTag:100];
[activityIndicator startAnimating];
return cell;
} else {
PilotObject *pilotObjDisplay = nil;
pilotObjDisplay = [_pilotsDisplay objectAtIndex:[_pilotsDisplay count]-1-indexPath.row];
static NSString *identifier = #"PilotCellTableViewCell";
PilotCellTableViewCell *cell = (PilotCellTableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
cell.hidden=NO;
cell.image.image = pilotObjDisplay.imageDisplayPilot;
cell.titleLabel.text = pilotObjDisplay.firstName;
cell.subTitleLabel.text = pilotObjDisplay.lastName;
cell.backgroundColor = [UIColor colorWithHexString:NSLocalizedString(#"gray_background", nil)];
return cell;
}
return nil;
}
Why you are taking 2 array _pilotsDisplay and _pilotsAll ?
If not necessary then you can also do pagination using one NSMutableArray which you can use in both cases while fetching data from server as well as while filling data to UITableView.
Remember one thing only initialise your NSMutableArray in viewDidLoad method. And when you received new data use addObject method of NSMutableArray which you are already using. And then call reloadData method of UITableView.
And in cellForRowAtIndexPath don't use calculation like [_pilotsDisplay count]-1-indexPath.row, simply use indexPath.row.
Here, inserting rows to the tableview may help you.
[tableView beginUpdates];
NSArray *paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:[dataArray count]-1 inSection:1]];
[[self tableView] insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationTop];
[tableView endUpdates];
You shouldn't add cells to a tableview. what you should do is add data to the tableview's datasource (in your case, _pilotsDisplay) and then simply reload the table. If you want the new data to appear at bottom or in any particular order, you should do that to your datasource (the array).
I'm implementing "swipe to delete" to a TableView with notifications from API. I created a method that deletes a notification when I hard-code its notification id (which is an array). The problem is I can't figure out how to get the exact notification id to delete.
There are TableView Delegate and TableView Data Source methods that somehow get the notification id, so I suppose I should be able to get it for the purpose of my method, but I've run out of ideas.
Here's my API source code:
desc 'delete notifications'
params do
requires :notification_ids, type: Array
end
delete 'notifications/remove', root: :notifications, each_serializer: NotificationSerializer do
require_authentication!
NotificationLogic.delete_notifications params[:notification_ids], current_user
current_user.notifications
end
Here's the method for deleting notifications:
-(void)deleteNotificationWithId:(NSArray*)ids withCompletionHandler:(DeleteNotificationCompletionHandler)handler
{
NSDictionary* params = #{ #"notification_ids" : ids };
__weak typeof(self) weakSelf = self;
ReadNotificationRequest* req = [ReadNotificationRequest new];
req.notificationIds = ids;
[_objectManager deleteObject:nil
path:#"user/notifications/remove"
parameters:params
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
_secondTry = NO;
NSArray* arr = mappingResult.array;
[self notififyAboutNotifications:arr];
handler(YES, arr, nil);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
if (operation.HTTPRequestOperation.response.statusCode == 401 && !_secondTry)
{
[weakSelf relogin:^{
[weakSelf deleteNotificationWithId:ids withCompletionHandler:handler];
}];
return;
}
handler(NO, nil, error);
}];
}
and implementation of the method in NotificationTableView. It works, but I hard-code the array with number:
-(void)setNotifications:(NSMutableArray *)notifications{
_notifications = notifications;
[self reloadData];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//Remove item in array
[self.notifications removeObjectAtIndex:indexPath.row];
// Also remove that row from the table view with an animation
[tableView deleteRowsAtIndexPaths:#[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
//Remove hard-coded notification from server
[[Api sharedInstance]deleteNotificationWithId:#[#756]
withCompletionHandler:^(BOOL succes, Message *response, NSError *error) {
if(succes){
} else {
[Utils alert:error.pop_message];
}
}];}
}
#pragma mark TableView Data Source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.notifications.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NotificationTableViewCell* cell = [self dequeueReusableCellWithIdentifier:#"NotificationTableViewCell"];
[cell configureCellWithNotification:self.notifications[indexPath.row]];
return cell;
}
#pragma mark - UITableViewDelegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
Notification* not = self.notifications[indexPath.row];
[self.notificationDelegate notificationTapped:not];
}
This code
//Remove item in array
[self.notifications removeObjectAtIndex:indexPath.row];
Deletes the information you need, just before you need it. Instead of deleting it, read the ID out first, then delete it and use the ID.
Have friendsviewcontroller in which have uibarbuttonItem to edit friends list and other uibarbuttonitem to create groups for group chatrooms.
Have multiple segue for switching view controllers.
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Groups";
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"New" style:UIBarButtonItemStylePlain target:self
action:#selector(actionNew)];
self.tableView.separatorInset = UIEdgeInsetsZero;
chatrooms = [[NSMutableArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if ([PFUser currentUser] != nil)
{
[self refreshTable];
}
else LoginUser(self);
}
#pragma mark - User actions
- (void)actionNew
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Create New Group" message:nil delegate:self
cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
}
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex: (NSInteger)buttonIndex=
{
if (buttonIndex != alertView.cancelButtonIndex)
{
UITextField *textField = [alertView textFieldAtIndex:0];
if ([textField.text isEqualToString:#""] == NO)
{
PFObject *object = [PFObject objectWithClassName:PF_CHATROOMS_CLASS_NAME];
object[PF_CHATROOMS_NAME] = textField.text;
[object saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
if (error == nil)
{
[self refreshTable];
}
else [ProgressHUD showError:#"Network error."];
}];
}
}
}
- (void)refreshTable
{
[ProgressHUD show:nil];
PFQuery *query = [PFQuery queryWithClassName:PF_CHATROOMS_CLASS_NAME];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (error == nil)
{
[chatrooms removeAllObjects];
for (PFObject *object in objects)
{
[chatrooms addObject:object];
}
[ProgressHUD dismiss];
[self.tableView reloadData];
}
else [ProgressHUD showError:#"Network error."];
}];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [chatrooms count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
PFObject *chatroom = chatrooms[indexPath.row];
cell.textLabel.text = chatroom[PF_CHATROOMS_NAME];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *chatroom = [chatrooms objectAtIndex:indexPath.row];
[chatrooms removeObjectAtIndex:chatroom];
//[chatrooms removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
PFObject *chatroom = chatrooms[indexPath.row];
NSString *roomId = chatroom.objectId;
CreateMessageItem([PFUser currentUser], roomId, chatroom[PF_CHATROOMS_NAME]);
ChatView *chatView = [[ChatView alloc] initWith:roomId];
chatView.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:chatView animated:YES];
}
Deleted row in table view reappears when navigate back to the TableView
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *chatroom = [chatrooms objectAtIndex:indexPath.row];
[chatrooms removeObjectAtIndex:chatroom];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
Im unable to locate what piece of code i m missing or what exactly i m doing wrong.
If anyone can please point out to that.
Will appreciate so much.
Thanks.
When committing deletion, your code removes objects from chatrooms which is data source of the table view in your case, but this happens in your app's memory, the source from which chatrooms is populated does not change. Thus, speaking in MVC, the app's model state is not updated after the view's state is changed.
Every time the table view is showed up, your code populates chatrooms in refreshTable, if the model's state hasn't been changed, the code gets same list as before, thus the table view doesn't change.
EDIT: Instead of using another approach to refresh the table view, you need to think about what does your app do in this table view. If user can delete stuff in the table view, should your app update model (This model can be a local or remote database, a property list file, etc.) too? If yes, then update model when user inserts or deletes rows in the table view; well, if not, then you are asking a question that is not a problem, or maybe the table view should turn off editing.
EDIT1:
If you do need to update data, based on your code, you may need to do something like this:
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *chatroom = [chatrooms objectAtIndex:indexPath.row];
[chatrooms removeObjectAtIndex:indexPath.row];
PFQuery *query = [PFQuery queryWithClassName:PF_CHATROOMS_CLASS_NAME];
[query deleteChatroom:chatroom];
[tableView deleteRowsAtIndexPaths:#[indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
That is, you may need to implement method deleteChatroom: of class PFQuery.
I'm getting this error when I try to delete a row. Please who can help me!!!!
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 3. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
//
// InboxTableViewController.m
// Ribbit
//
// Created by OnMac on 24/11/14.
// Copyright (c) 2014 OnMac. All rights reserved.
//
#import "InboxTableViewController.h"
#import "ImageViewController.h"
#interface InboxTableViewController ()
#end
#implementation InboxTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.recipient = [NSMutableArray arrayWithArray:[self.selectedMessage objectForKey:#"recipientIds"]];
NSLog(#"Delete: %#", self.selectedMessage);
self.moviePlayer = [[MPMoviePlayerController alloc] init];
PFUser *currentUser = [PFUser currentUser];
if (currentUser) {
NSLog(#"Currrent user: %#", currentUser.username);
}
else {
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
}
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFUser *currentUser = [PFUser currentUser];
if (currentUser) {
PFQuery *query = [PFQuery queryWithClassName:#"Message"];
[query whereKey:#"recipiendID" equalTo:[[PFUser currentUser] objectId]];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else{
// We found messages!!!
self.messages = objects;
[self.tableView reloadData];
// NSLog(#"messages: %#", self.messages);
}
}];
}
else {
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [self.messages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
// Configure the cell...
PFObject *message = [self.messages objectAtIndex:indexPath.row];
cell.textLabel.text = [message objectForKey:#"Username"];
// NSLog(#"ALT: %#", message);
NSString *fileType = [message objectForKey:#"fileType"];
if ([fileType isEqualToString:#"image"]) {
PFFile *im = [message objectForKey:#"file"];
NSData *resumeData = [im getData];
cell.imageView.image = [UIImage imageWithData:resumeData];
}
else{
cell.imageView.image = nil;
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedMessage = [self.messages objectAtIndex:indexPath.row];
NSString *fileType = [self.selectedMessage objectForKey:#"fileType"];
if ([fileType isEqualToString:#"image"]) {
[self performSegueWithIdentifier:#"showImage" sender:self];
}
else{
// File type is video
PFFile *videoFile = [self.selectedMessage objectForKey:#"file"];
NSURL *fileUrl = [NSURL URLWithString:videoFile.url];
self.moviePlayer.contentURL = fileUrl;
[self.moviePlayer prepareToPlay];
// Add it to the view controller so we can see it
[self.view addSubview:self.moviePlayer.view];
[self.moviePlayer setFullscreen:YES animated:YES];
}
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
PFObject *message1 = [self.messages objectAtIndex:indexPath.row];
[message1 deleteInBackground];
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
[self.tableView reloadData];
}
- (IBAction)logout:(id)sender {
[PFUser logOut];
[self performSegueWithIdentifier:#"showLogin" sender:self];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"showLogin"]) {
[segue.destinationViewController setHidesBottomBarWhenPushed:YES];
}
else if ([segue.identifier isEqualToString:#"showImage"]) {
[segue.destinationViewController setHidesBottomBarWhenPushed:YES];
ImageViewController *imageViewController = (ImageViewController *)segue.destinationViewController;
imageViewController.message = self.selectedMessage;
}
}
#end
First, please edit your code more. You have more white space than actual code, and pasting that much white space just makes the process longer.
Second, try reading the error message. It's saying that you are deleting a row from the datasource when you aren't removing it from the table. What I suspect is happening is inside your commitEditingStyle method:
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
PFObject *message1 = [self.messages objectAtIndex:indexPath.row];
[message1 deleteInBackground];
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
[self.tableView reloadData];
}
Look at what you're doing. There's a lot of issues here. First, you're deleting a message 100% of the time this method is called. That means you're always modifying your datasource. But look at your if statement - this means that you are not always deleting a row. Now you sometimes delete a message without deleting the row from the table. This WILL cause the crash.
Second - from what it sounds like, it sounds like you're deleting the message in the background. This is potentially a very bad thing. Why? Because if you're waiting on a delegate callback in an asynchronous fashion, then this will lead to very bad race conditions.
Your code should look like this:
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *message1 = [self.messages objectAtIndex:indexPath.row];
[self.messages removeObject:message1];
[message1 deleteInBackground];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
}
Note that I added [self.messages removeObject:message1] to make your dataSource consistent with the table immediately. I don't know what you were doing in [PFObject deleteInBackground], but if you weren't immediately removing the message object from your dataSource, then you can run into bad issues.
I am trying to delete a row in a UITableView (PFQueryTableViewController). The object deletes in the class, but is only reflected in the table when I refresh the table. Here is the code I am using.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *object = [self.objects objectAtIndex:indexPath.row];
[object deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
[tableView reloadData];
}];
}
}
Sussed it.
Instead of [tableView reloadData], I've used [self loadObjects].
However, the usual delete animation is not there.
You have to make all UI updates in main thread.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *object = [self.objects objectAtIndex:indexPath.row];
[object deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[tableView deleteRowsAtIndexPaths:#[indexPath]withRowAnimation:UITableViewRowAnimationFade];
}];
}
}