UITableView: load all cells - objective-c

Is it possible to load all cells of an UITableView when the view is loaded so that they are not loaded when I'm scrolling?
(I would show a loading screen while doing this)
Please, it's the only way at my project (sorry too complicate to explain why ^^)
EDIT:
Okay let me explain you, what I'm definite doing:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [NSString stringWithFormat:#"Identifier %i/%i", indexPath.row, indexPath.section];
CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSDictionary *currentReading;
if (cell == nil)
{
cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
UILabel *label;
UIView *separator;
if(indexPath.row == 0)
{
// Here I'm creating the title bar of my "table" for each section
}
else
{
int iPr = 1;
do
{
currentReading = [listData objectAtIndex:iPr-1];
iPr++;
} while (![[currentReading valueForKey:#"DeviceNo"] isEqualToString:[devicesArr objectAtIndex:indexPath.section]] ||
[readingresultsArr containsObject:[currentReading valueForKey:#"ReadingResultId"]]);
[readingresultsArr addObject:[currentReading valueForKey:#"ReadingResultId"]];
//
// ...
//
}
}
return cell;
}
My error happens in the do-while-loop:
"listData" is an array with multiple dictionaries in it.
My problem ist that when I’m scrolling my table slowly down, all is fine, but when I’m scrolling quickly to the end of the view and then I’m scrolling to the middle, I get the error that iPr is out of the array’s range. So the problem is, that the last row of the first section has already been added to the "readingresultsArr", but has not been loaded or wants to be loaded again.
That’s the reason why I want to load all cells at once.

You can cause all of the cells to be pre-allocated simply by calling:
[self tableView: self.tableView cellForRowAtIndexPath: indexPath];
for every row in your table. Put the above line in an appropriate for-loop and execute this code in viewDidAppear.
The problem however is that the tableView will not retain all of these cells. It will discard them when they are not needed.
You can get around that problem by adding an NSMutableArray to your UIViewController and then cache all the cells as they are created in cellForRowAtIndexPath. If there are dynamic updates (insertions/deletions) to your table over its lifetime, you will have to update the cache array as well.

put a uitableview on a uiscrollview
for example , you expect the height of the full list uitableview is 1000
then set the uiscrollview contentsize is 320X1000
and set the uitableview height is 1000
then all cell load their content even not visible in screen

In my case it was that I used automaticDimension for cells height and put estimatedRowHeight to small that is why tableview loaded all cells.

Some of the answers here and here suggest using automaticDimension for cells height and put mytable.estimatedRowHeight to a very low value (such as 1).
Starting with iOS 15 this approach seems not to work anymore. Hence, another way to achieve the table to "load" all cells could be by automatically scrolling to the last cell. Depending on the tables height and how many rows it can show some cells are discarded but each cell would be loaded and shown at least once.
mytable.scrollEnabled = YES;
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:cellCount - 1 inSection:0];
[mytable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
mytable.scrollEnabled = NO;
If you want to scroll up again just scroll to the top as outlined here.

Following the comment that was made by juancazalla, I found that if you have a tableView that is using automaticDimension, loading all the cells at once can be best achieved by setting estimatedRowHeight to a low value (such as 1).

Related

How to use Autolayout and self-sizing cells in iOS8

I have setup the auto-sizing cells with UILabels with no problem in iOS8 following this tutorial:
http://useyourloaf.com/blog/2014/08/07/self-sizing-table-view-cells.html
But I am having problems setting up a UIImageView using auto-sizing. I need the images to be different sizes in Landscape compared to portrait (so they retain the same aspect ratio). But each time I get a broken layout constraints error
"<NSLayoutConstraint:0x14554680 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x14564440(200)]>
As the actual code has quite a few different types of cell (that all work with auto-sizing cells) I have setup a simple example of the issue with a blue image view here:
https://github.com/AdrianMW/ios8autosizingCells
I have setup the constraints to the superview and am setting up the height like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ImageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kImageCell forIndexPath:indexPath];
cell.heightConstraint.constant = [self heightForOrientation:self.interfaceOrientation];
return cell;
}
Solutions Tried
I have tried turning off setTranslatesAutosizingMask: on the cell as per some of the other suggestions but when I do I just get a blank space instead of a image. I have also tried adding the following:
[cell setNeedsDisplay];
[cell layoutIfNeeded];
I have seen mention of overriding sizethatfits: to get it to work on this cell using the old way but that doesn't seem to be called on the cell.
Cheers
In your ImageTableViewCell.xib, try changing the constraint:
Image View.Bottom EQUAL Superview.Bottom
Change the priority from 1000 to 999.

UITableViewCell ReuseIdentifier Behavior [obj-c]

I am curious as to the behavior of the reuse identifier system.
I am working with a uitableviewcell that has two different uilabels on them.
Label one is always there and is updating correctly,
Label two starts with .alpha=0 and appears on a certain condition within the specific cell.
Label one is acting as suspected,
Label two acts strangely, when I first load the scene(viewdidload) it appears as it should.
When I scroll down and find a uitableviewcell has the labeltwo with .alpha=1 because it satisfied the conditional.
Up to this point everything is working, but now if I scroll back up, all label two's have an .alpha=1.
After doing some research, I have come to the conclusion that this has to do with me redefining what the reuse identifier cell template actually looks like programatically.
My question is , is there a way to reset the "buffer" to the uitableview cell i have created in storyboard that DOESNT have the changes I have made programatically.
Also since these are my own deductions, I may be incorrect in my assumptions,
Thanks for your time.
Your cells begins .alpha = 1, because of reuseIdentifier, that already see .alpha = 1, and set another sell to this parameter. As a first decision, you can control .alpha parameter for the each cell individually.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"FeedbackCell";
VZDetailFeedbackTableViewCell *cell = (VZDetailFeedbackTableViewCell *)[self.p_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[VZDetailFeedbackTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// There can be more cells with Identifier
CGFloat alpha = 1.0f;
//if (something)
{
alpha = 0.0f;
}
[cell setSellAlpha:alpha];
}
// In your custom cell class you make method setAlpha and there control visibility

Object/Item out of UICollectionView cells instead of index?

I've been trying to save the state or order of cells in a UICollectionView after they have changed locations in the UICollectionView. When I use indexPathsForVisibleItems I get indexes that are always in the same order. They do not reflect order change. If I could get the object at each indexPath I could at least make an attempt to iterate through them to get the resulting order.
I used this code. And found that it returned a refreshed state of indexPaths in [0,0]. The ordering is always the same because the it tells me what cells have something in them not what is in each cell. I just don't know enough or where to start to get the object/item in each cell.
NSArray *visible = [self.collectionView indexPathsForVisibleItems];
NSMutableArray *rowsArray = [NSMutableArray arrayWithCapacity:[visible count]];
[visible enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) {
[rowsArray addObject:#(indexPath.item)];
I need the items or objects at each location. How do I iterate through all the cell locations to retrieve the item there. I plan on using the count of an array used to populate the UICollectionView to loop through all the locations and get the object stored there. There is only one section and cells seem to be storing objects like this <Slide: 0x7585200>
The function above returns NSLogs in this format "<NSIndexPath 0x8490390> 2 indexes [0, 0]"
I need to get what is in that location.
I'm not familiar with NSIndexPath or it's formatting. Even just the command/function would help for me to get an object out. Thanks.
(Addendum) I'm think of using something like [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; Not sure what I can store it in.
CollectionView is a collection of UIViews (call UICollectionViewCell). Each cell has an indexPath (section,row) mean the layout position in collectionView content. In the case you has 1 section, section always = 0.
visibleCells mean all cells visible on screen at that time (visible in scroll frame or collectionView frame).
indexPathsForVisibleItems = indexPath array of visibleCells
cellForItemAtIndexPath is a method to get a collectionViewCell at any indexPath you want, often use to get cell when select:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
NSLog(#"%#",cell);
}
Investigate more from Apple UICollectionView video and example:
https://developer.apple.com/library/ios/#samplecode/CollectionView-Simple/Introduction/Intro.html
https://developer.apple.com/videos/wwdc/2012/

ProgressView wont update in tableview

I am trying to update a custom tableview cell's progressview but the progress view wont update.
I can set the labels on the tableview cell but accessing things like progress bars or activity indicators doesnt work.
I do the following on the custom cell
cell.progressView.hidden = NO;
cell.progressView.progress = 0.5;
[cell.progressView setNeedsDisplay];
This doesnt work even though in the debugger I see the object is of the correct cell type and the progressView is allocated.
I have tried setNeedsDisplay on the cell itself as well, but no luck. What am I missing?
Calling [self tableView:tableView cellForRowAtIndexPath:indexPath]; is most likely the problem because this likely results in another cell being dequeued from the table. So you end up setting up a new cell, not the one currently being display.
Instead, do this:
CustomTableViewCell *cell = (CustomTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
This directly asks the table for the cell. This should return the currently displayed cell if the row is visible.

How does manually assigning tableView.rowheight affect subviews of the given Table View?

I have a custom view for displaying application status messages that I slide over my table view as needed. This worked fine until I started customizing my table view cells.
When I manually assign a row height to my table view cells in initWithSTyle...
self.TableView.rowHeight = 64.0;
...the custom view doesn't show up anymore.
I replaced the code above with a delegate method...
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 64.0;
}
...and now the custom view works as before.
Set rowHeight in the view controller.
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.rowHeight = 64.0f;
}
I think initWithStyle is too early to set the height. Eitherway, since your height is constant, it's still more efficient to set the height once (in viewDidLoad) than set it every time for each cell created (in initWithStyle or heightForRowAtIndexPath).
Did you create a custom cell class inheriting UITableVIewCell , if yes , then the height of customcell is different than the height of default cell.So you need to change the height of row to match your customcell;s in order for it to desplay correctly,Else cellswill overlap.
To Dynamically set height accoring to your customcell:-
YourCustomCell *cell = (YourCustomCell *)[tableView cellForRowAtIndexPath:indexPath];
return [cell.frame.size.height];
maintableView = [[UITableView alloc] init];
maintableView.frame = CGRectMake(0, 0, 320, 480);
maintableView.rowHeight = 100.0;
maintableView.delegate=self;
maintableView.dataSource=self;
It is working in my Xcode. Try like it. I think it will work.