Different UITableView scrolling performance on iPad 2 & iPhone 4s - ios

Solved
There was a shadow on the self.view layer. After removed it, the tableview scrolls smoothly (56-59fps).
The problem I got is so weird.
I am building a UITableView based Twitter like App. After optimized the table view loading and scrolling, I tested the App (same code & same UI) on both iPad 2 and iPhone 4S. On the iPad 2, I got 56-59fps smooth scrolling animation. But on the iPhone 4S, I got only 43-49fps scrolling animation, which is awful.
This seems not caused by the Retina display. After I remove all images from cells, the problem is still there. The following is the code of cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// fetch note from the fetched results controller
Note *note = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([note.photos count] > 0) {
static NSString *CellIdentifier = #"Photo Cell";
PhotoCell *cell = (PhotoCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[PhotoCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
} else {
[cell clearContents];
}
NSNumber *currentRowNumber = [NSNumber numberWithInt:indexPath.row];
// check if the photos of this cell has been pre loaded
NSDictionary *coverImages = [self.coverImagesForNotes objectForKey:currentRowNumber];
if (coverImages == nil) {
if (self.tableView.dragging == NO && self.tableView.decelerating == NO) {
coverImages = [self loadCoverImagesForCell:indexPath photos:note.photos];
[self.coverImagesForNotes setObject:coverImages forKey:currentRowNumber];
}
}
// assign contents to the cell
[self compositeContentView:cell forNote:note rowNumber:indexPath.row];
// refine
unsigned textContentHeight = [[self.cellTextHeightDict objectForKey:currentRowNumber] integerValue];
unsigned currentPageNumber = [self currentPageNumberAtRow:indexPath.row];
[cell initPhotoVideoView:textContentHeight photos:note.photos coverImages:coverImages showPage:currentPageNumber rowNumber:indexPath.row];
cell.delegate = self;
return cell;
} else {
static NSString *CellIdentifier = #"Simple Cell";
BaseCell *cell = (BaseCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[OneViewBaseCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// assign contents to the cell
[self compositeContentView:cell forNote:note rowNumber:indexPath.row];
return cell;
}
}
Thanks for answers.

Are you using images in your table view cells? This will be more expensive on a retina display. Also if you are using images, try to load them in on a background thread which will reduce the latency.
If you're not using images then you should really look at how you are creating your cells, please post tableView:cellForRowAtIndexPath: method implementation

Related

Custom cells in UITableView become blank after scrolling up or down

I was tasked to solve this bug in the app (It's for comercial use so I can't link the project). I'm also completely new to Objective-C or IOS development and I have no idea why the following happens. Reminder, I'm using custom cells.
When the tableview loads, everything looks fine.
Click here to see the example
But when I scroll up and back to the same postion the cell becomes blank, as if it had no data. Blank cell
If I repeat the same process everything looks fine again.
Here's the code for cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellId = #"cell2";
PedTableCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil)
{
cell = [(PedTableCell*)[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
if (tableView==_table3)
{
NSString *docsDirr;
NSString *documentsDirectoryForSaveImages;
docsDirr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
documentsDirectoryForSaveImages = [docsDirr stringByAppendingPathComponent:#"/CarpetaImatges"];
NSString *match = #".jpg";
NSString *preCodigo;
NSScanner *scanner = [NSScanner scannerWithString:[pedarray objectAtIndex:indexPath.row]];
[scanner scanUpToString:match intoString:&preCodigo];
NSString *nomimg=[NSString stringWithFormat:#"%#.jpg", preCodigo];
UIImage *img = [UIImage imageWithContentsOfFile:[documentsDirectoryForSaveImages stringByAppendingPathComponent:nomimg]];
cell.img.image = img;
cell.layer.borderWidth=1.0f;
cell.img.layer.borderWidth=1.0f;
cell.cart.text = preCodigo;
cell.descart.text = [nomarray objectAtIndex:indexPath.row];
cell.cant.text = [cantarray objectAtIndex:indexPath.row];
cell.precart.text = [precioarray objectAtIndex:indexPath.row];
cell.pvpcart.text = [pvparray objectAtIndex:indexPath.row];
[cell layoutIfNeeded];
}
return cell;
}
I've debugged the method and everytime it returns a valid cell. When I click the empty cell it still works as expected. Essentially, the data is there, it's just not rendered for some reason.
I've checked other posts with the same/similar issue but nothing seems to really match. PrepareForReuse is a no go since there's no UI to be changed, just content. I'm getting the values of the arrays with indexPath.row to make sure I'm fetching the correct value. I've even tried to set the heightForRowAtIndexPath to the same height the cell should have (all cells are of the same size and never change) or let AutoLayout handle it but to no avail.
Code of numberOfRowsInSection (Returns the amount of orders that exists in database currently):
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if(tableView == _table3)
{
[self cargacarro];
return pedarray.count;
}
return pedarray.count;
}
Any ideas?
Register your cell nib in storyboard or in code before tableview is loaded, and after replace dequeueReusableCell... with this one
PedTableCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
cell.img...
cell.cart...
remove this part, is no longer needed
if (cell == nil)
{
cell = [(PedTableCell*)[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}

Cropped Text on TableViewController

(iOS 6.1.6, iPod Touch 4th Gen, Xcode 7)
Using the default "Subtitle" format for a TableViewController, I'm getting data that looks like this. Scrolling will sometimes refresh so it shows correctly, but not always. I've tried widening the labels in the prototype cell, but that doesn't seem to make a difference.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Creating Cell");
static NSString *tableID = #"locationOverviewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableID];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableID];
}
cell.textLabel.text = ((PullLocation *)WarehouseLocations[indexPath.row]).WarehouseLocation;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d Items To Pull",(int)((PullLocation *)WarehouseLocations[indexPath.row]).NumItemsToPull];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
Can anyone point me in the right direction?

iOS 8 UITableView placing

With iOS 8 I have come up with some issues using UITableView. In fact, I have a NavigationController and its RootController set as my ViewController with UITableView. Then I configure my table, add cells and set their style to UITableViewCellStyleValue1 and nothing happens at the time it should display a detailed text label to the right of the textLabel. I suppose that there is some missing constraints preventing from displaying the whole cell's view.
My code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"STI";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
}
cell.textLabel.text = self.dwarves[indexPath.row];
cell.detailedLabel.text = #"Detailed text";
UIImage *img = [UIImage imageNamed:#"star"];
cell.imageView.image = img;
return cell;
}
What I get:
I think the property you're looking for is cell.detailTextLabel, not cell.detailedLabel.
Take a look at this post.
The code I use for setting up my detailed text:
if (indexPath.row < 7) {
cell.detailTextLabel.text = #"First";
} else {
cell.detailTextLabel.text = #"Second";
}
I'm in the process of updating an old app for iOS 8 and ran into the same issue. I haven't discovered the root of the problem yet, but calling layoutSubviews for the cell before returning it fixed it for me.
...
[cell layoutSubviews];
return cell;
}

UITableViewCell with UIScrollView cause content of other cells disappearing

I was trying to find solution almost everywhere, but I didn't find it. So, here is my problem.
I have UITableView with custom UITableViewCells.
The first cell has UIScrollView inside its Content View.
The Second cell has UILables and other basic views inside its Content View.
So, if there is UIScrollView inside the first cell, content of the second cell disappears. It appears only if the first cell scrolls out of the tableView frame.
Can anybody help me figure it out? Thank you.
Code preview
#pragma mark - UITableView Data Source
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath isEqual:_photosIndexPath]) {
static NSString *PhotosCellIdentifier = #"AdDetailsPhotosCell";
BazarAdDetailPhotosCell *cell = [tableView dequeueReusableCellWithIdentifier:PhotosCellIdentifier];
if (!cell) {
cell = [[BazarAdDetailPhotosCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:PhotosCellIdentifier];
}
cell.photoScrollView.scrollsToTop = NO;
cell.photoScrollView.delegate = cell;
[cell setPhotos:_adDetail.photos];
return cell;
}
else if ([indexPath isEqual:_adDetailsPath]) {
static NSString *DetailsCellIdentifier = #"AdDetailsDetailCell";
BazarAdDetailsDetailCell *cell = [tableView dequeueReusableCellWithIdentifier:DetailsCellIdentifier];
if (!cell) {
cell = [[BazarAdDetailsDetailCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:DetailsCellIdentifier];
}
cell.adTitleLabel.text = _adDetail.title;
cell.priceLabel.text = _adDetail.price;
// this cell content disappears
}
}
Might be issue with cell drawing on iOS 7.1, according answer on iOS 7.1 beta5 tableviewcell height showing objects outside it's range, try to clip subviews:
cell.clipsToBounds = YES;
Try it
#pragma mark - UITableView Data Source
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath isEqual:_photosIndexPath])
{
static NSString *PhotosCellIdentifier = #"AdDetailsPhotosCell";
BazarAdDetailPhotosCell *cell = [tableView dequeueReusableCellWithIdentifier:PhotosCellIdentifier];
if (!cell) {
cell = [[BazarAdDetailPhotosCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:PhotosCellIdentifier];
}
cell.photoScrollView.scrollsToTop = NO;
cell.photoScrollView.delegate = cell;
[cell setPhotos:_adDetail.photos];
return cell;
}
else {
static NSString *DetailsCellIdentifier = #"AdDetailsDetailCell";
BazarAdDetailsDetailCell *cell = [tableView dequeueReusableCellWithIdentifier:DetailsCellIdentifier];
if (!cell) {
cell = [[BazarAdDetailsDetailCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:DetailsCellIdentifier];
}
cell.adTitleLabel.text = _adDetail.title;
cell.priceLabel.text = _adDetail.price;
// this cell content disappears
return cell;
}
}

UILabel inside cell in UITableView is always null (two cell prototypes)

I am trying to populate cells in table view ( I have two custom types of cells with with different elements created in storyboard, with identifiers "info_cell" and "person_cell", on segmented control above UITableView I decide what to load [tableView reload]). When I try to access UILabels inside cell I get that labels are null.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = (viewType == INFO_VIEW) ? #"info_cell" :#"person_cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if(viewType == INFO_VIEW){
NSLog(#"INFO = %#", info_text_some_string);
UILabel *lblInfo = (UILabel *)[cell viewWithTag:200];
[lblInfo setText:info_text_some_string];
}
else{
// there is part for person
}
return cell;
}
Same code works when I have just one prototype cell inside table (UITableView is inside UIVewController). What can be problem here, I have checked 100 times: cell identifiers are OK, label tag is 200.
This is action for UISegmentControl
- (IBAction)changeView:(id)sender {
UISegmentedControl *segmentedControl = (UISegmentedControl *) sender;
NSInteger selectedSegment = segmentedControl.selectedSegmentIndex;
if (selectedSegment == 0) {
viewType = INFO_VIEW;
}
else{
viewType = PERSON_VIEW;
}
[tableView reloadData];
}
I have added and necessary methods for tableView and connect delegate i datasource.
Does anyone have any idea why it is null ?
Try this usually i follow this process whenever i go with custom cell in CellRorRowAtIndexPath
if(!cell)
{
cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
//customcell is your UITableViewCell created by you in ur xib
NSData *archivedData =[NSKeyedArchiver archivedDataWithRootObject:customcell];
cell =[NSKeyedUnarchiver unarchiveObjectWithData:archivedData];
}
if(viewType ==INFO_VIEW)
{
[(UILabel *)[cell viewWithTag:200] setText:#"you text"];
}
else{
// person view....
}
This way your collecting all your elements of your cell and setting value for it. share your results please
Assuming that you have subclass your UITableViewCells correctly (I use InfoCell and PersonCell for example), you can try this:
if(viewType == INFO_VIEW)
{
InfoCell *cell = (InfoCell *)[tableView dequeueReusableCellWithIdentifier:#"info_cell"];
// do your stuff for info here
}
else if(viewType == PERSON_VIEW)
{
PersonCell *cell = (PersonCell *)[tableView dequeueReusableCellWithIdentifier:#"person_cell"];
// do your stuff for person here
}
Why not do something like this?
[[cell textLabel] setText: #"text goes here"];
And skip the UILabel part?

Resources