I am trying to follow the following post on reload a cell in a UICollectionView:
UICollectionView update a single cell
I know that I ultimately want something that looks like this:
[self.collectionView reloadItemsAtIndexPaths:??];
But I don't know how to find and pass the indexPath of a particular cell. Can anyone provide any pointers?
I have an NSMutableArray that contains all the cell information (imageViews that are generated in each cell). Ideally, what I'd like to do is pass the index of the NSMutableArray to refresh the corresponding cell on the page. But I'm not sure how the numerical index gets translated into an indexPath.
Thanks in advance for your help!
It depends on your implementation and how you have grouped your cells into sections but let's assume you have one section and each element in your array corresponds to a row in your table.
If you wanted to reload a cell corresponding to an array element at index x all you need to do is write
[_collectionView performBatchUpdates:^{
[_collectionView reloadItemsAtIndexPaths:#[[NSIndexPath x inSection:0]]];
} completion:^(BOOL finished) {}];
Conversely, if you have the cell but want to find its index path you can always call [collectionView indexPathForCell:myCell]
Toy have to pass an array containing the indexPaths that you want to be reloaded.
[self.collectionView reloadItemsAtIndexPaths: indexpathArray];
NSIndexPath has some property names section and row, both represents a cell. If your collection view has single section, you can create a NSIndexPath by setting its section = 0;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:0];
Here rowIndex is your array index. Btw you have to make an array with you newly created indexpaths, then pass it to reloadItemsAtIndexPaths.
Hope this helps.. :)
Obj-C
NSMutableArray *indexPaths = [[NSMutableArray alloc] init]
[indexPaths addObject:indexPath];
[self.collectionView reloadItemsAtIndexPaths: indexPaths];
Swift 4.0
var indexPaths = [IndexPath]()
indexPaths.append(indexPath)
if let collectionView = collectionView {
collectionView.reloadItemsAtIndexPaths(indexPaths)
}
You can use this way for Swift 5.1:
collectionViewOutletName.reloadItems(at: [IndexPath(row: indexNumber, section: sectionNumber)] )
You can use this way for Swift 5:
CollectionView.reloadItems(at: IndexPath])
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dic = #{#"option":[NSNumber numberWithBool:YES]};
[self.array insertObject:dic atIndex:indexPath.row];
[collectionView reloadItemsAtIndexPaths:#[indexPath]];
}
Related
I am building an IOS application where I am using tableView. Now when I reached to last cell I load +10 data from localDB.
After fetching the data I reloaded the tableView that I don't need in place of reload I want to used updated tableView. for that SOF suggested me below code.
[[self tableView] beginUpdates];
[[self tableView] reloadRowsAtIndexPaths:____ withRowAnimation:UITableViewRowAnimationAutomatic];
[[self tableView] endUpdates];
I don't what should be there in reloadRowsAtIndexPaths value. Please can some help me in understanding this above line of code.
You can get the indexPath of the last row in last section like this.
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(numberOfRowsInLastSection - 1) inSection:(numberOfSections - 1)];
Here, numberOfSections is the value you return from numberOfSectionsInTableView: method. And, numberOfRowsInLastSection is the value you return from numberOfRowsInSection: method for the last section in the table view.
You don't need to reload cells, because there are no cells after your 10th cell. You want your users to see more cells when they get to the last one as in a news app. The solution is to inset more rows below, here is how:
1- create the rows you want to insert
NSMutableArray *newRows = #[[NSIndexPath indexPathForRow:10 inSection:0]];
3- update your data source array
2- [self.tableView insertRowsAtIndexPaths: newRows, UITableViewRowAnimationAutomatic];
Thanks in advance. I'm dealing with a single UITableView which is divided into different sections. Users can add or delete cells only from specific sections. The information displayed in the UITableView is stored in an array where each object represents a section:
eg: tableItemsArray = ((arrayForSection1), (arrayForSection2), (arrayForSection3))
I have the animation set up to handle the delete as follows:
[tableView deleteRowsAtIndexPaths:#[indexPath]
withRowAnimation:UITableViewRowAnimationRight];
I then programmatically remove the item from the array to remove it from the data model. However I am having difficulty in how to insert the cell in an animated form.
Currently I am running the current pseudo-algorithm:
Check item isn't anywhere in the array
Add item to array into a specific section
sort this section of the array alphabetically
reload the data
Update
When a new item is added to the array it is stored in a string to keep record of the new item. Once the array has been resorted I iterate through the array of cells to find its indexPath, then I delete the string (to prevent recursive insertion animations) and perform the animation, however the code doesn't animate its insertion into the table. I wondered whether that maybe the animation code (as below) wasn't working as I was using [tableView reloadData]?
// For Each Section in the table:
for (NSMutableArray *object in sectionsInTable) {
// For Each Cell in a section (Cells are stored in an array in index 1)
for (NSString *label in [object objectAtIndex:1]) {
if ([label isEqualToString:_insertedObject]) {
// New item
_insertedObject = Nil;
// animate addition
[self.labelListTableView beginUpdates];
[self.labelListTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:[[object objectAtIndex:1] indexOfObject:label] inSection:[sectionsInTable indexOfObject:object]]] withRowAnimation:UITableViewRowAnimationBottom];
[self.labelListTableView endUpdates];
}
}
}
Any ideas why the animation isn't working?
Thanks
D
Seems that the [tableView reloadData] was preventing the animation.
// Annimate the new Item
// For Each Section in the table:
for (NSMutableArray *object in sectionsInTable) {
// For Each Cell in a section:
for (NSString *cell in [object objectAtIndex:1]) {
if ([cell isEqualToString:_insertedObject]) {
// New item
_insertedObject = Nil;
// animate addition
[tableView beginUpdates];
NSInteger section = [sectionsInTable indexOfObjectIdenticalTo:object];
NSInteger row = [[object objectAtIndex:1] indexOfObjectIdenticalTo:cell];
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:row inSection:section];
[tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationBottom ];
[tableView endUpdates];
}
}
}
What I have
1). Container has UITableView, which has two custom UITableViewCells.
2). Core Data has certain entity which has a text to be displayed at
UITableViewCell each time I get into the View.
What i am doing ?
1) I have chosen -viewWillAppear method which gets invoked each time the view is visible.
2) In -viewWillAppear, I retrieved the data from core data.
3) Retrieved particular cell from UITableView
NSUInteger idxArr[] ={2,0}; // 2 nd section, 0th Row.
NSIndexPath *cPath = [NSIndexPath indexPathWithIndexes:idxArr length:2];
myCell *tCell = (myCell *)[self.settings cellForRowAtIndexPath:cPath];
tCell.myLabel.text = rec.servername; // rec.servername is from DC.
When I checked in the lldb,
tCell was nil.
Questions:
1) It is the right way of getting the Cell ?
2) Or, By the time -viewWillAppear, does the UITableView not Ready ?
I am sure.
You should populate the cells by conforming to tableView dataSource protocol and then in your viewWillAppear you should call reloadData on your tableView.
After calling reloadData for tableview, We need to call -scrollToRowAtIndexPath: before getting cell from -cellForRowAtIndexPath:.
Because, As we are calling a row in section 2, it might not be in the visible area until we scroll. So, cellForRowAtIndexPath: returns nil.
Method -cellForRowAtIndexPath: shouldn't be called programically. It's a data source method for UITableView and it contain some cell reuse optimalizations. If you update the view after scrolling down and up -tableView:cellForRowAtIndexPath will be called again and your changes won't be visible.
If you want to update specific cell you should update make changes in:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
YourCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellId" forIndexPath:indexPath];
YourData *data = //Get your data here
if (data.isReady) {
cell.tf.text = data[indexPath.row].text;
} else {
cell.tf.text = #"Not ready yet. Need to reload this cell later";
}
return cell;
}
And then call method below when you finish fetch your data.
[self.tableView reloadRowsAtIndexPaths:(NSArray *) withRowAnimation:UITableViewRowAnimationFade];
If you want to reload whole tableView (usually it's not slow) as #salaman140 says you can call [self.tableView reloadData] to update all visible cells.
If I were you I wouldn't use:
NSUInteger idxArr[] ={2,0}; // 2 nd section, 0th Row.
NSIndexPath *cPath = [NSIndexPath indexPathWithIndexes:idxArr length:2];
I would (is much more clear):
NSIndexPath *cPath = [NSIndexPath indexPathForRow:0 inSection:2];
I am a new IOS Programmer, and i am having a issue.
I have a UITableView with 2 sections, one then is static, and another one is dynamical.
In specific actions i need to add new rows for the second section in runtime..
I know how to manage a UITableView , but not a specific section
Could you help me please?
Best Regards you all
You can use insertRowsAtIndexPaths: method of UITableView
//Update data source with the object that you need to add
[tableDataSource addObject:newObject];
NSInteger row = //specify a row where you need to add new row
NSInteger section = //specify the section where the new row to be added,
//section = 1 here since you need to add row at second section
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationRight];
[self.tableView endUpdates];
You can use the same method insertRowAtIndexPath like
// Add the items into your datasource object first. Other wise you will end up with error
// Manage the number of items in section. Then do
NSIndexPath *indexPath1 = [NSIndexPath indexPathForRow:0 inSection:1];
NSIndexPath *indexPath2 = [NSIndexPath indexPathForRow:1 inSection:1];
[self.tableView insertRowsAtIndexPaths:#[indexPath1,indexPath2] withRowAnimation:UITableViewRowAnimationTop];
This will insert two rows to the section1. Remember before doing this you have manage your datasource object.
Swift 3 version
// Adding new item to your data source
dataSource.append(item)
// Appending new item to table view
yourTableView.beginUpdates()
// Creating indexpath for the new item
let indexPath = IndexPath(row: dataSource.count - 1, section: yourSection)
// Inserting new row, automatic will let iOS to use appropriate animation
yourTableView.insertRows(at: [indexPath], with: .automatic)
yourTableView.endUpdates()
you can do this by using scrolltoinfinite method but before that u have to import 3rd party svpulltorefresh
[self.tableViewMixedFeed addInfiniteScrollingWithActionHandler:^{
CGFloat height = self.tableViewMixedFeed.frame.size.height;
CGFloat contentYoffset = self.tableViewMixedFeed.contentOffset.y;
CGFloat distanceFromBottom = self.tableViewMixedFeed.contentSize.height - contentYoffset;
if(distanceFromBottom<contentYoffSet)
{
[weak insertRowAtBottom];
}
}];
-(void)insertRowAtBottom
{
[self.tableViewMixedFeed beginUpdates];
[self.tableViewMixedFeed insertRowsAtIndexPaths:indexPaths1 withRowAnimation:UITableViewRowAnimationTop];
[self.tableViewMixedFeed endUpdates];
[self.tableViewMixedFeed.infiniteScrollingView stopAnimating];
}
here indexpaths1 is the array of indexpaths of next cells which u want to insert in a table .
try using loop to get the next set of arrays and store them into indexpaths1.
[self.tableView insertRowsAtIndexPaths:#[indexPath1,indexPath2] withRowAnimation:UITableViewRowAnimationTop];
USE THIS METHOD..
I have a uitableview that hosts a number of cells, in another part of the app the user will make an NSString selection that will match on of the cells in the uitableview, how can I select hat cell programmatically?
I tried using the method
selectRowAtIndexPath:animated
but how can I get the indexpath? is there a better way?
I think you are loading data from an array. Then just search inside that NSArray and take index of the matched object. Now you can create NSIndexPath programatically:
[NSIndexPath indexPathForRow:index inSection:section];
Just use this NSIndexPath to select the row
try this .... first try to get the cell number based on string
NSString * pUserSelectedString = #"abcd";
int index;
if([array containsObject:pUserSelectedString])
{
index = [array indexOfObject:pUserSelectedString];
}
The way you needs to get the indexpath from source array is
int selectionIndex;
if([sourceArray containsObject:userSelectionString])
{
selectionIndex = [sourceArray indexOfObject:userSelectionString];
}
You have to check whether selection object is there or not before get the indexpath from sourceArray.then you have to use this indexpath for selectRowAtIndexpath:animated method