Dynamically adding content to UICollectionView - ios

I have a UICollectionView that is backed by a web service. I initially load 100 items from the service into the collection view. When the user reaches the bottom of the view, I dyanmically load the next "page" of content.
This is working, but my collectionView flashes and re-draws the entire view from the top. I am trying to get it to just begin drawing the new content at the bottom of the view.
Code for adding new content to the collectionview:
- (void)insertIntoCollectionView: (int) itemCnt {
// only do the batchupdate for NON-initial load
if(curPage != 0) {
// Add items to main photos array, and update collectionview using batchUpdate
[self.collectionView performBatchUpdates:^{
// Get starting size before update
int resultsSize = itemCnt;
// Create a new array to hold the indexpath for the inserted data
NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];
// Add indexpath objects to the new array to be added to the collection view
for (int i = resultsSize; i < resultsSize + itemCnt; i++) {
[arrayWithIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
// Update the collectionview
[self.collectionView insertItemsAtIndexPaths:arrayWithIndexPaths];
}
completion:nil];
} else {
[self.collectionView reloadData];
}
curPage++;
Anything obvious? It functionally works, but looks pretty bad with all of the flashing and re-drawing.

OK, managed to fix it myself. I was using the incorrect values for the resultSize variable. The for loop should start at the end of the current array count, and loop through the number of item that we added, thus adding them at the end. I was starting at the beginning of the array index 1 when building the arrayWithIndexPaths, causing it to re-draw the whole view.

Related

UITableView Load more autosrolling issue

Folks,
I am getting a weird issue while applying scroll to load more to my UITableView. I added a YouTube video also for reference. At scrolling to bottom, API hits server and gets next 5 records. At this time I am not reloading the table, neither I want too. I am simply adding more rows to the table. The code is below:
// adding new rows rather than reloading the table
if(loadMore)
{
NSMutableArray *indexPaths = [NSMutableArray array];
for (NSUInteger i = 0; i < arr.count; i++)
{
[indexPaths addObject:[NSIndexPath indexPathForRow:arr.count+i inSection:0]]; // adding max 5 new indexPaths
}
[self.tblData beginUpdates];
[self.tblData insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; // insert with fade animation
[arrData addObjectsFromArray:arr]; // adding new data to existing array
[self.tblData endUpdates];
}
Now see the video I uploaded. On 1st load more it works like charm. You can see it at 00:07. It adds 5 more rows at the bottom with fade animation.
But after 1st load more, for next 5 load more it brings 5 more records from the server and adds them to the table but also it autoscrolls at the same index, see video at 00:15, 00:23, 00:30 an so on.
You can see it works good on 1st load more (at 00:07), but never after that even all the records are coming good.
After that I changed simulator animation to Slow and you can see that after 01:01
Can anyone suggest me why it is happening? Somewhere I found it is due to AutoLayout, then i made another storyboard which has disabled autolayout but problem still occurs.

UITableviewcells become null after the 3rd add

I have an UITableview with custom UITableviewCell that has 2 Text Fields.
I have a button that adds new cells to this table. Initially i have 3 cells then I add and I add and when i add the sixth (6th) cell it crashes saying the cell is empty when i iterate over it like this:
NSMutableArray *cells = [[NSMutableArray alloc] init];
for (NSInteger j = 0; j < [shtoFushaTableView numberOfSections]; ++j)
{
for (NSInteger i = 0; i < [shtoFushaTableView numberOfRowsInSection:j]; ++i)
{
NSLog(#"%#", [shtoFushaTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]]);
[cells addObject:[shtoFushaTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]]]; //this is where i get an exception to add a null object
}
}
The point of this iteration is to store the values of the text fields before adding a new one.
Any Idea what im doing wrong ?
The problem is probably the re-use of table view cells:
When they are scrolled out of view, they are put back in a cell pool, and all data in the cells might disappear.
For this reason you should never store anything in a table view cell except for display.
You have to store your data in a data model, and read them from there for display in the cells.

Cannot refresh 1 cell in UICollectionview iOS

I have added 1 new cell in my UICollectionView, but it only refreshes after I scroll down and scroll to top, and that cell will be appeared. I want it will appeare immediately after inserting a new cell, without scrolling. I tried the following code. Please help me to correct it.
[self performBatchUpdates:^{
self.arrayWithIndexPaths = [NSMutableArray array];
[self.arrayWithIndexPaths addObject:[NSIndexPath
indexPathForRow:_numberOfItemsInCollectionView -1
inSection:SECTION_COUNT-1]];
[self insertItemsAtIndexPaths:self.arrayWithIndexPaths];
//prepare generate XML
[self prepareForGenerateXML:selectedItemsArray andCameraMode:NO];
} completion:nil];

scrollToRowAtIndexPath doesn't scroll to correct position when segment value changed

I have a segment control with a table view. When user clicks segment control, then table view changes data source. I would like table to scroll to last position user had seen.
For example: user was in segment 1 and looking at table view line 3.
segment 1 | segment 2
line 3
line 4
line 5
Then user clicked segment 2 then clicked back to segment 1. I want table view scroll to line 3.
Code is as below. In viewDidAppear I have same code to get lastSavedRow and call scrollToRowAtIndexPath. When app gets loaded the scrolling works. However, in segmentValueChanged action it doesn't roll to correct position. In debugger I am sure the lastSavedRow has correct number.
- (IBAction) segmentVauleChanged : (id)sender
{
// remember row number before segment value changes
NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];
NSArray * sortedIndexPaths = [indexPaths sortedArrayUsingSelector:#selector(compare:)];
NSIndexPath *firstVisibleIndexPath = [sortedIndexPaths objectAtIndex:0];
// function to write row number and seg index to user default
[self saveScrollPositionInSegment: self.currentSegmentSelectedIndex row:firstVisibleIndexPath.row];
self.currentSegmentSelectedIndex = segmentController.selectedSegmentIndex;
[self.tableView reloadData];
// scroll to last saved position
int lastSavedRow = [self getScrollPositionInSegment:segmentController.selectedSegmentIndex];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:lastSavedRow inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
Does anyone have same problem? Many thanks in advance!
The lastSavedRow will on the top of the current tableview. I think there maybe something wrong with the dealing with datasource. Maybe after change the datasource, the last postion the user seen was not the index you figured out!
If you provide more information or your example, we can help you to find out the mistake.
I would do the following.
1 .Call visibleCells before calling indexPathsForVisibleRows
[self.tableView visibleCells];
2.Look at the need for sorting the array before identifying firstVisibleIndexPath
3.reloadData is not synchronous so its possible that the table is not completed loading before you try to scroll to an index. So try to see if you can do the scrolling in one of the delegate functions instead of here. See this.
hackerinheels 's (3) is right. reloadData hasn't finished when scrolling table is called. So I added the code:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
if (section == ([self.tableView numberOfSections] - 1)) {
//NSLog(#"finish loading");
// put the scrolling table call here: [self scrollTableView ];
}
return nil;
}
Thank you all for helping!

Capture the index value of a cell but only from the visible cells on the screen

I am trying to trigger some code based on if the cell I selected becomes the first or last cell on the users screen. I'm not trying to capture the index value of the data array. Just the index value of the cell that is visible on the screen. I'm sure this to create an array of visible cells.
NSArray *indexPathsForVisibleRows = [myTableView
indexPathsForVisibleRows];
But I keep hitting a dead end trying to then capture an index value based on that array.
I tried to use a CGPoint and convert that, but I keep getting an error. Any insight would be most helpful!
As per the documentation for the return value of that method:
An array of NSIndexPath objects each representing a row
index and section index that together identify a visible row in the
table view. Returns nil if no rows are visible.
The array returned from that method contains NSIndexPaths.
NSArray *indexPathsForVisibleRows = [myTableView indexPathsForVisibleRows];
for(NSIndexPath *eachIndexPath in indexPathsForVisibleRows)
{
NSInteger row = eachIndexPath.row;
NSInteger section = eachIndexPath.section;
UITableViewCell *cell = [myTableView cellForRowAtIndexPath:eachIndexPath];
if(cell.isSelected)
{
// this is our selected cell
}
}

Resources