I have gif animated pictures in some uitableview rows,
When there is a lot of gifs in tableview CPU usage is going to be very high,
So I want to hide these gifs when their row is not visible,
How can I do that ?
How can I achieve not visible cells row's indexPath ?
After that I can hide the gif like that :
UITableViewCell *celll = [ tableView cellForRowAtIndexPath:indexPath];
UIImageView *gif = (UIImageView*)[celll viewWithTag:30000];
gif.hidden = TRUE;
So I must get not visible cells indexPath's in a loop.
Generally, you don't need to do that as long as you properly use reusable cells.
Nevertheless, if you do want to do that, you can use tableView:didEndDisplayingCell:forRowAtIndexPath: method on UITableViewDelegate:
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath {
UIImageView *gif = (UIImageView*)[celll viewWithTag:30000];
gif.hidden = YES;
}
If you'll put the line:
NSLog(#"%#",indexPath);
as the first line of the method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
You'll realise that it's done automatically. Only the visible cells, i.e the one that appears on the screen, are the one you present the data for.
Sorry for poor english.You had not posted code about how your cellForRowAtIndexPath implementation look like,i will suggest to make your cellForRowAtIndexPath like below.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"YOURIDENTIFIERSTRING";
UITableViewCell *cell = [tableView dequeReusableCellWithIdentifier: CellIdentifier forIndexPath:indexPath];
// Configure the cell here …
return cell;
}
This way only those many cells will be created which are visible on device and once row goes out of device view it will be reuse for new row. Please check apple doc for tableview.
Related
I am working with tableviews in iOS. Reusable cells are reloaded when scrolling.
So, when updating -for example- textfields inside a cell, it disappears once scrolling over. I solved it by using an Array that saves all texts in all cells, but I wonder if there's a better way to solve this issue.
Thanks.
Using String array you have to store data of all textfields in tableview.
Use delegate methods of UITableView to implement more efficiently.
-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell * mc = (MyCell *) cell;
names[indexPath.row] = mc.myTf.text;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell * mc = (MyCell *) cell;
mc.myTf.text = names[indexPath.row];
}
Here, MyCell is the custom cell which has UITextField. name[] is the NSString array declared at class scope like NSString * names[20].
What you are describing is how tableviews are meant to work! The tableView is a display, not a store, and the reusable cells are only those currently displayed
You are right to use an array (or collection) to hold the data and just use the tableView to display it
for memory management (to releasing memory) tableview remove cell memory which are not displaying in current screen its only keep those cell in memory which are currently displaying on screen so you have to store that text separate from tableview.
You issue can be because of multithreading. If you are reloading data from a GCD operation or any NSOperation(different thread), then you have to use the below code to get the handle to main thread
dispatch_sync(dispatch_get_main_queue(), ^{
//perform the reload activity
});
Yes you are doing right, as cells are reused you need to save your data, something like this -
1 . Have an array to hold your data.
2 . Update your array whenever you make any change in your textFields, so that your UI and data are in sync.
Use this array to populate your tableView.
You need to define the cellIdentifier as unique. Then each cell created with unique identifier.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%dR%d",indexPath.section,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
//your logic here
}
return cell;
}
I am trying to work with UICollectionView that is a part of the UITableViewCell.
So the issue I faced, the collection view for visible table cells works ok, but when I start scroll table and table starts create new cells that where invisible then I faces with some behaviour that duplicate first table cell. For example I have scrolled collection view in first table view cell, then I scrolled table view down, and what I see the new cell have the same state as my first cell had. You can check source here repo and the video here to understand what I am talking about.
Have a property of UICollectionView in CustomTableViewCell.h and bind it in Main.storyboard. Let's assume declared it like this:
#property (strong, nonatomic) UICollectionView *collectionView;
In ViewController.m change cellForRowAtIndexPath method, so it reloads inside UICollectionView every time it need
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CustomTableViewCell"];
[cell.collectionView reloadData];
[cell.collectionView scrollRectToVisible:CGRectZero animated:NO];
return cell;
}
Of course, you need to import CustomTableViewCell.h on ViewController.m file.
-[UITableViewCell prepareForReuse]
Problem with reuse identifier in UITableView cell, if you use single cell identifier in cellForRowAtIndexPath this problem will occurs
1. Use Dynamic cell identifier for each row, like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:#"CustomTableViewCell_%d",indexPath.row]];
}
2.Store content offset for each collection view in array, and reset collection view content offset
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
......
[cell.collectionView setContentOffset:scrollingPoint animated:NO];
return cell;
}
I have a simple UITableView
I'm doing my first Edit implementation, to add Delete functionality. Most of this stuff is the default apparently. Pretty much the only method I added to my Controller is
- (void) tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
Program *victim = Site.current.sortedPrograms[indexPath.row];
[Site.current removeProgram: victim];
[self.tableView
deleteRowsAtIndexPaths: #[indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
When I hit the Edit button, I see
which is good. But When I hit the minus button on one with a shorter title, I see the following
The title is completely scrolled out of site! Similarly, if I use the iOS 7 swipe left gesture, even on a longer title, the title is scrolled out of view:
The code I use to create the cell is pretty simple:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ProgramCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Program *program = Site.current.sortedPrograms[indexPath.row];
cell.textLabel.text = program.name;
cell.detailTextLabel.text = [program.script prettyCycleDuration];
return cell;
}
This isn't what I want my users to see. I would rather see it scroll the title only if necessary, so that context (not whitespace) associates with the delete button. I am just using a stock UITableViewCell (not a subclass), and I'm setting the 'style' to Subtitle. I've looked at the delegate methods, and a book I have, but I don't see anything that shows how to deal with this. Is there a way? Will I need to do my own Cell subclass and handle the states more explicitly? Or is there something else I can do?
Update
Even after converting to a custom subclass, with constraint based layouts for my cell, it still slides the whole view over, rather than compress it.
I have been looking for answers for more than 2 days now. It just does not seem to solve.
Here is the code for cell
- (myCustomCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CustomData *m = (CustomData *)[self.allCustomData objectAtIndex:indexPath.row];
static NSString *CellIdentifier = #"customCell";
myCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[cell setBackgroundColor:[UIColor colorWithRed:255.0f green:255.0f blue:255.0f alpha:1]];
[cell.customTitle setText:m.name];
[cell.customStatus setText:#"Download"];
NSLog(#"%#",cell.customTitle.text);
return cell;
}
'cell' never returns nil. the log always prints the correct text. But the cells appear empty for some reason. On load I notice the first cell appears empty, and then on scroll, randomly 2-3 cells of any order become empty. The first cell often appears back on scroll.
I can't seem to understand what the issue could be.
UPDATE
Here are two screen shots. First one is how the table loads, I have put a background color just for debugging purpose. As you see the first cell is not showing up.
The one below is the second screenshot where I changed the orientation and scrolled a bit. You see how the first cell magically appears and the second goes away.
Also for debugging purpose, I added these two methods.
- (void)tableView:(UITableView *)tableView willDisplayCell:(dtEditionCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"Display %# %d %f",cell.editionTitle.text,indexPath.row,cell.frame.origin.x);
}
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(dtEditionCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"End Display %# %d %f",cell.editionTitle.text,indexPath.row,cell.frame.origin.x);
}
The log prints as expected. All cells are visible with correct text.
I don't know if it has something to do, but the method you show is not exactly the one used by the tableview. Here is how I do it with custom cells. I'm doing it a lot and works fine:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TextCell *cell = [tableView dequeueReusableCellWithIdentifier:#"textCellId" forIndexPath:indexPath];
TextFieldContent *cellContent=[[self.dataSource objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
cell.titleLabel.text=cellContent.titleLabel;
cell.textField.placeholder=cellContent.placeHolder;
cell.textField.tag=cellContent.tag;
cell.textField.keyboardType=UIKeyboardTypeDecimalPad;
cell.textField.delegate=self;
return cell;
}
TextFieldContent is a cutom object that hold all the properties of the custom cell. For easier implementation.
I need to have a custom cell height for all of my cells in my UITableView. In this method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
I try this:
if ([[tableView cellForRowAtIndexPath:indexPath] reuseIdentifier] == #"imageCell")
As I have 3 different cells setup with different identifiers in my storyboard. However my app just crashes here with EXC_BAD_ACCESS.
Any idea why?
Thanks.
You're comparing a string, so you should be using isEqualToString:
if ([[[tableView cellForRowAtIndexPath:indexPath] reuseIdentifier] isEqualToString:#"imageCell"])
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
you are supposed to calculate the height for you row, not to get the Cell of your tableView.
In my opinion, in the lifeCycle of a TableView delegate, the 1st step (before allocating each UITableViewCell), the TableView delegate call heightForRowAtIndexPath for each row (but at this moment, the UItableViewCell are not allocated). The, in a 2nd step, the TableView call
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
to create UitableView Cells.