iOS Objective C - UITableView performance issue - ios

My app is using CoreData as persistence data storage. Below is my code for the tableview. On the simulator it runs fine, but when running it on the phone it gets very laggy. Any suggestions on optimization is appreciated :)
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
Journal* journal = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.titleLabel.text = journal.title.uppercaseString;
cell.titleLabel.font = [UIFont fontWithName:#"SourceSansPro-Bold" size:25];
cell.titleLabel.textColor = [UIColor blackColor];
cell.detailLabel.text = journal.detail;
cell.detailLabel.font = [UIFont fontWithName:#"SourceSansPro-SemiBold" size:18];
cell.detailLabel.textColor = [UIColor blackColor];
NSDate *currentDate = journal.timeStamp;
cell.dateLabel.text = [self.dateFormatter stringFromDate: currentDate];
cell.dateLabel.font = [UIFont fontWithName:#"SourceSansPro-SemiBold" size:16];
cell.dateLabel.textColor = [UIColor blackColor];
cell.locationLabel.text = [NSString stringWithFormat:#"%#, %#", journal.city, journal.country];
cell.locationLabel.font = [UIFont fontWithName:#"SourceSansPro-SemiBold" size:18];
cell.locationLabel.textColor = [UIColor blackColor];
cell.tempLabel.text = [NSString stringWithFormat:#"%g°C", round(journal.temp)];
cell.tempLabel.font = [UIFont fontWithName:#"SourceSansPro-SemiBold" size:18];
cell.tempLabel.textColor = [UIColor blackColor];
cell.weatherIcon.image = [UIImage imageNamed:journal.condition];
cell.backgroundView = [[UIImageView alloc] initWithImage:[ [UIImage imageWithData:journal.image] stretchableImageWithLeftCapWidth:0.0 topCapHeight:5.0] ];
cell.backgroundView.contentMode = UIViewContentModeScaleAspectFill;
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[ [UIImage imageWithData:journal.image] stretchableImageWithLeftCapWidth:0.0 topCapHeight:5.0] ];
cell.selectedBackgroundView.contentMode = UIViewContentModeScaleAspectFill;
cell.backgroundView.alpha = 0.5;
cell.selectedBackgroundView.alpha = 0.5;
return cell;
}

You are experiencing low FPS lags because of this API usage:
[UIImage imageWithData:journal.image]
The UIImage imageWithData: method is NOT asynchronous, so as the table view loads each new cell, it has to process the data, locking up the app while doing so.
Try to find an async way to load/create/cache an image on a background thread making your UI responsive.
Check out this popular image loading/caching library SDWebImage for more ideas/inspiration and potential solution for your needs.

First, you can customize a cell, some code is unnecessary, such as set Font and TextColor in every time.
Next, you can use instrument-->Profile to find the code where is time consuming.
Hope it can help you!

Related

UIProgressView update itself in custom UITableViewCell

I've a UITableView populated with several custom UITableViewCell. In one of them I have a UIProgressView that will represent a percentage of data.
However when I set a progress (let's say 50%), the progress bar appear at 50% and update itself until it reach 100%...
Here the code I use to update the data :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = [menuItems objectAtIndex:indexPath.row];
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if ([appliedTheme hasPrefix:#"DarkMode"]) {
self.tableView.backgroundColor = [UIColor colorWithRed:0.20 green:0.20 blue:0.20 alpha:1.0];
cell.backgroundColor = [UIColor colorWithRed:0.20 green:0.20 blue:0.20 alpha:1.0];
cell.cardView.backgroundColor = [UIColor colorWithRed:0.30 green:0.30 blue:0.30 alpha:1.0];
cell.storageIntroLabel.textColor = [UIColor whiteColor];
cell.storageInfoTitle.textColor = [UIColor whiteColor];
cell.deviceStorageTitle.textColor = [UIColor whiteColor];
}else {
self.tableView.backgroundColor = [UIColor colorWithRed:0.92 green:0.92 blue:0.92 alpha:1.0];
cell.backgroundColor = [UIColor colorWithRed:0.92 green:0.92 blue:0.92 alpha:1.0];
cell.cardView.backgroundColor = [UIColor whiteColor];
cell.storageIntroLabel.textColor = [UIColor blackColor];
cell.storageInfoTitle.textColor = [UIColor blackColor];
cell.deviceStorageTitle.textColor = [UIColor blackColor];
}
if ([CellIdentifier isEqualToString:#"storageIntro"]) {
cell.storageIntroImageView.image = [UIImage imageNamed:storageIntroIconToShow];
cell.storageIntroLabel.adjustsFontSizeToFitWidth = YES;
cell.storageIntroLabel.numberOfLines = 0;
[cell.storageIntroLabel sizeToFit];
cell.storageIntroLabel.text = NSLocalizedString(#"Here you can find informations about your storage and how FileStore is using your memory by types of files", nil);
}else if ([CellIdentifier isEqualToString:#"storageInfo"]){
cell.storageInfoTitle.text = NSLocalizedString(#"Storage Informations", nil);
cell.deviceStorageTitle.adjustsFontSizeToFitWidth = YES;
cell.deviceStorageTitle.text = NSLocalizedString(#"Device Storage", nil);
cell.totalDeviceSpaceLabel.adjustsFontSizeToFitWidth = YES;
cell.totalDeviceSpaceLabel.text = NSLocalizedString(#"Total space :", nil);
cell.finalTotalDeviceSpaceLabel.text = totalDeviceSpaceString;
cell.freeDeviceSpaceLabel.adjustsFontSizeToFitWidth = YES;
cell.freeDeviceSpaceLabel.text = NSLocalizedString(#"Free space :", nil);
cell.finalFreeDeviceSpaceLabel.text = totalDeviceFreeSpaceString;
dispatch_async(dispatch_get_main_queue(), ^{
[cell.deviceStorageProgressView setProgress:50 animated:YES];
});
}else {
}
return cell;
}
Even if I doesn't use the bool animated:YES, the progress bar update itself over the time from the percentage I've set...
It doesn't mean anything to me ! Do I have to put the UIProgressView settings in another cell's delegate method ?
Thanks in advance for your help !
According to UIProgressView documentation
The current progress is represented by a floating-point value between 0.0 and 1.0, inclusive, where 1.0 indicates the completion of the task. The default value is 0.0. Values less than 0.0 and greater than 1.0 are pinned to those limits.
You are setting it to 50 which will basically be converted to upper value 1. You need to give value as 0.5 if you want 50% progress.

UITableViewCell with subviews is not working properly

I have UITableView in my iOS app and I want to add some subviews to cell. I do it by using
[cell.contentView addSubview:someView];
and it works well, but... When I scroll down, subviews are starting to hide from cells that are on top and when I scroll back to top, they wont appear again... What I'm doing wrong? Is there some solution please?
EDIT
Mainly, I'm talking about "detailtext" label, but I have those problems in more cases...
Here is whole code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
switch (indexPath.row) {
case 0:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
break;
default:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
break;
}
UIView *separatorLine = [[UIView alloc] init];
separatorLine.frame = CGRectMake(15.0f, 60 - 0.5f, cell.frame.size.width-15.0f, 0.5f);
separatorLine.tag = 4;
separatorLine.backgroundColor = [UIColor lightGrayColor];
cell.layer.masksToBounds = NO;
tableView.backgroundColor = [UIColor colorWithRed:33.0 / 255.0 green:157.0 / 255.0 blue:147.0 / 255.0 alpha:1.0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIView *row2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];
UIView *profileBorder = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-50, 50, 102, 102)];
profileBorder.layer.borderColor = [UIColor whiteColor].CGColor;
profileBorder.layer.borderWidth = 5; //2
profileBorder.layer.cornerRadius = 50;
NZCircularImageView *profileImage = [[NZCircularImageView alloc] initWithFrame:CGRectMake(1,1, 100, 100)];
profileImage.image = profilePhoto;
profileImage.contentMode = UIViewContentModeScaleAspectFill;
UITapGestureRecognizer *showBigProfilePhoto = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showImage:)];
profileImage.userInteractionEnabled = YES;
[profileImage addGestureRecognizer:showBigProfilePhoto];
[profileBorder addSubview:profileImage];
UILabel *numberFeelings = [[UILabel alloc] initWithFrame:CGRectMake(10, 100-25, 100, 50)];
numberFeelings.text = [NSString stringWithFormat:#"%#\nFeelings", feelings];
numberFeelings.font = [UIFont boldSystemFontOfSize:16];
numberFeelings.textAlignment = NSTextAlignmentCenter;
numberFeelings.textColor = [UIColor whiteColor];
numberFeelings.numberOfLines = 0;
UILabel *numberFriends = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2+60, 100-25, 100, 50)];
numberFriends.text = [NSString stringWithFormat:#"%#\nFollowers", friends];
numberFriends.font = [UIFont boldSystemFontOfSize:16];
numberFriends.textColor = [UIColor whiteColor];
numberFriends.numberOfLines = 0;
numberFriends.textAlignment = NSTextAlignmentCenter;
[row2 addSubview:profileBorder];
[row2 addSubview:numberFriends];
[row2 addSubview:numberFeelings];
int rectButtons = cell.frame.size.width-246;
UIImageView *graph = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2, -20, 82, 82)];
UIImageView *badgets = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2+82, -20, 82, 82)];
UIImageView *photos = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2+164, -20, 82, 82)];
graph.image = [UIImage imageNamed:#"graph.jpg"];
badgets.image = [UIImage imageNamed:#"badgets.jpg"];
photos.image = [UIImage imageNamed:#"photos.jpg"];
graph.userInteractionEnabled = YES;
badgets.userInteractionEnabled = YES;
photos.userInteractionEnabled = YES;
UITapGestureRecognizer *graphTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showGraph:)];
[graph addGestureRecognizer:graphTap];
NSArray *jmenoCasti = [name componentsSeparatedByString:#" "];
krestni = [jmenoCasti objectAtIndex:0];
int indexOfPost = indexPath.row-3;
NSMutableAttributedString *str;
int countFeeling;
int countString;
int countBeforeFeeling;
if (indexPath.row >=3) {
str = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#"%# was %#", krestni, [naladyHim objectAtIndex:[[[posts objectAtIndex:indexOfPost] objectForKey:#"_feel"] integerValue]]]];
countFeeling = [[naladyHim objectAtIndex:[[[posts objectAtIndex:indexOfPost] objectForKey:#"_feel"] integerValue]] length];
countString = krestni.length+5+countFeeling;
countBeforeFeeling = countString-countFeeling+1;
int rangeStart = countBeforeFeeling-1;
int rangeStop = str.length-rangeStart;
NSLog(#"%i ... %i", countBeforeFeeling-1, countString-1);
[str addAttribute:NSFontAttributeName value: [UIFont fontWithName:#"Helvetica-Bold" size:16.0f] range:NSMakeRange(rangeStart, rangeStop)];
[str addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:32.0 / 255.0 green:147.0 / 255.0 blue:138.0 / 255.0 alpha:1.0] range:NSMakeRange(rangeStart, rangeStop)];
}
UILabel *mainText = [[UILabel alloc] initWithFrame:CGRectMake(15, 70, cell.frame.size.width-10, 20)];
mainText.attributedText = str;
UILabel *detailText;
if (!detailText) {
detailText = [[UILabel alloc] initWithFrame:CGRectMake(15, 90, cell.frame.size.width-10, 30)];
}
detailText.textColor = [UIColor grayColor];
detailText.font = [UIFont systemFontOfSize:13];
switch (indexPath.row) {
case 0:
cell.textLabel.textAlignment = NSTextAlignmentCenter;
cell.textLabel.text = name;
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.font = [UIFont systemFontOfSize:20];
cell.backgroundColor = [UIColor clearColor];
break;
case 1:
[cell.contentView addSubview:row2];
cell.backgroundColor = [UIColor clearColor];
break;
case 2:
cell.backgroundColor = [UIColor colorWithRed:236.0 / 255.0 green:235.0 / 255.0 blue:210.0 / 255.0 alpha:1.0];
[cell.contentView addSubview:graph];
[cell.contentView addSubview:badgets];
[cell.contentView addSubview:photos];
break;
default:
detailText.text = [[posts objectAtIndex:indexPath.row-3] objectForKey:#"_text"];
[cell.contentView addSubview:detailText];
cell.textLabel.attributedText = str;
cell.backgroundColor = [UIColor colorWithRed:236.0 / 255.0 green:235.0 / 255.0 blue:210.0 / 255.0 alpha:1.0];
break;
}
return cell; }
This is an easy way thats works for me:
for(UIView *subview in cell.contentView.subviews)
{
if([subview isKindOfClass: [UIView class]])
{
[subview removeFromSuperview];
}
}
You can use it at the begin of
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
In your tableView:cellForRowAtIndexPath:, you hide the info when you don't want it to be shown, but you don't explicitly unhide it for cells where it should be shown.
Look at the first two lines in that method: What you are - correctly - doing is reusing your cells, so when cells are scrolled out of view, they are removed from the UITableView and put into the reuse queue. Then, when cells should become visible, the TableView gets cells from that queue - or creates new ones if none are available.
This all goes very well, but after a while, cells with hidden info buttons are put on the queue. And then, some time later, those cells are reused - and sometimes for rows in which there should be info visible.
There are two solutions to this: You could either explicitly unhide the information for those rows where you want it to be shown, or you could use two different kinds of cell, one with hidden info, and one with visible info. You then give each of those cells a different identifier, and based on what row the cells are in, set the identifier before dequeuing/creating cells.
You should create a subclass of UITableViewCell for each different cell and add all your view related code that doesn't change depending on the data into an initialization method. Then create a method in each cell called something like configureWithData and pass in the data relevant to the cell. The creation of your attributed string and modification of label frames can occur in this configuration method.
It will dramatically reduce the clutter in your UITableViewController and is much better design wise. There is no real need for your view controller to know what your table cells look like.
Here is an example of what I am talking about:
-(void)awakeFromNib
{
if( self.accessoryType == UITableViewCellAccessoryDisclosureIndicator )
{
DTCustomColoredAccessory *accessory = [DTCustomColoredAccessory accessoryWithColor:[UIColor whiteColor]];
accessory.highlightedColor = [UIColor blackColor];
self.accessoryView = accessory;
}
}
-(void)configureCellWithObject:(id)inObject
{
TableDataModel *dataObject = (TableDataModel *)inObject;
self.titleLabel.text = dataObject.titleString;
self.subtitleLabel.text = dataObject.subtitleString;
self.accessibilityIdentifier = dataObject.accessIdString;
if( dataObject.imageUrlString != nil )
{
UIImage *iconImage = [UIImage imageNamed:dataObject.imageUrlString];
if( iconImage != nil )
{
NSInteger yOffset = [StaticTools centerYOffset:self.frame.size objectFrameSize:iconImage.size];
self.iconImageView.image = iconImage;
CGRect frame = self.iconImageView.frame;
frame.origin.y = yOffset;
frame.size = iconImage.size;
[self.iconImageView setFrame:frame];
}
else
{
[self.iconImageView loadImageFromUrl:dataObject.imageUrlString];
}
}
}

UICollectionView poor scrolling performance

The problem I encounter is that whenever a row goes out of view, the scroll has a very fast and short lag.
This is my code:
- (UICollectionViewCell *)collectionView:(UICollectionView *)_collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [self.collView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
Saints *note = nil;
int aX=0;
int aY=0;
note = [self.fetchedResultsController objectAtIndexPath:indexPath];
for (UIView *view in cell.contentView.subviews) {
if([view isKindOfClass:[UIImageView class]])
{
[view removeFromSuperview];
}
else if([view isKindOfClass:[UILabel class]])
{
[view removeFromSuperview];
}}
cell.backgroundColor = [UIColor clearColor];
UIImage *imgbackground = [UIImage imageNamed:#"today-left-side-images-bg.png"];
NSArray *messages = [[NSArray alloc] initWithObjects: #"random-saint-text-bg-brown.png",#"random-saint-text-bg-brightblue.png",#"random-saint-text-bg-green.png",#"random-saint-text-bg-grey.png",#"random-saint-text-bg-lightblue.png",#"random-saint-text-bg-lime.png",#"random-saint-text-bg-purple.png",#"random-saint-text-bg-red.png",#"random-saint-text-bg-teal.png",nil];
int randNum = arc4random() % [messages count];
NSString *returnValue = [messages objectAtIndex:randNum];
NSString *rndBGImg= returnValue;
UIImage *imgbackgroundlower = [UIImage imageNamed:rndBGImg];
UIImageView *imgViewlower = [[UIImageView alloc] initWithImage:imgbackgroundlower];
//imgViewlower.frame=CGRectMake(aX, aY+140, 140,73);
imgViewlower.frame=CGRectMake(aX+4, aY+114, 119,43);
UIImageView *imgView = [[UIImageView alloc] initWithImage:imgbackground];
imgView.frame=CGRectMake(aX, aY, 127,162);
UIImageView *imgSaintPic = [[UIImageView alloc]init];
imgSaintPic.tag=1;
imgSaintPic.frame=CGRectMake(aX+6, aY+6, 114,145);
//NSString *imgname = [aDic objectForKey:#"saint_image"];
NSString *imgname = note.saint_imagethumbnail;
UIImage *tempimg= [UIImage imageNamed:imgname];
[imgSaintPic setImage:tempimg];
UILabel *lblNamelocal=[[UILabel alloc]init];
NSString *strSaintName=note.saint_name;
//lblNamelocal.text=strSaintName;
if([note.saint_title length]>1)
lblNamelocal.text=[NSString stringWithFormat:#"%# %#",note.saint_title,strSaintName];
else
lblNamelocal.text=[NSString stringWithFormat:#"%#",strSaintName];
//lblNamelocal.frame = CGRectMake(aX+6, aY+109, 116,30);
[lblNamelocal sizeToFit];
lblNamelocal.frame = CGRectMake(aX+5, aY+115, 118,26);
lblNamelocal.lineBreakMode = UILineBreakModeWordWrap;
lblNamelocal.numberOfLines = 0;
lblNamelocal.backgroundColor = [UIColor clearColor];
lblNamelocal.textColor = [UIColor whiteColor];
lblNamelocal.font = [UIFont fontWithName:#"HelveticaNeue-CondensedBold" size:11 ];
// lblNamelocal.textAlignment=UITextAlignmentLeft;
lblNamelocal.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
lblNamelocal.shadowColor = [UIColor darkGrayColor];
lblNamelocal.shadowOffset = CGSizeMake(0,0.5);
lblNamelocal.textAlignment = UITextAlignmentCenter;
UILabel *lblsubtitle=[[UILabel alloc]init];
//NSString *strSaintSubtitle=[aDic objectForKey:#"saint_title"];
lblsubtitle.text=note.saint_subtitle;
//lblsubtitle.frame = CGRectMake(aX+6, aY+132, 116, 25);
lblsubtitle.frame = CGRectMake(aX+5, aY+140, 113, 20);
lblsubtitle.lineBreakMode = UILineBreakModeWordWrap;
lblsubtitle.numberOfLines = 2;
lblsubtitle.backgroundColor = [UIColor clearColor];
lblsubtitle.textColor = [UIColor whiteColor];
lblsubtitle.font = [UIFont fontWithName:#"HelveticaNeue" size:10];
// Removed CJamesRun lblsubtitle.textAlignment=UITextAlignmentLeft;
lblsubtitle.shadowColor = [UIColor darkGrayColor];
lblsubtitle.shadowOffset = CGSizeMake(0,0.5);
lblsubtitle.textAlignment = UITextAlignmentCenter;
imgViewlower.tag=3;
lblNamelocal.tag=2;
lblsubtitle.tag=4;
[cell.contentView addSubview:imgView];
[cell.contentView addSubview:imgSaintPic];
[cell.contentView addSubview:imgViewlower];
[cell.contentView addSubview:lblNamelocal];
[cell.contentView addSubview:lblsubtitle];
// cell.layer.masksToBounds = NO;
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
return cell;
}
What I've tired is to rasterize the cell layer, and also to remove the views from the SuperView upon creating a new cell.
Any other suggestions?
I would recommend setting up your cells' subviews just once, and then only updating the contents inside collectionView:cellForItemAtIndexPath:. E.g. you're loading some images in each cell, but those are the same for every cell, so loading them every time the cell is reused is unnecessary.

Why does sizeToFit remove my entire label?

I am trying to use the function sizeToFit. It works perfectly throughout the application however it does not work in the code below. Further to that, if it can't be done the way I am doing it please advise.
self.label = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 67.0, 290, 50)];
self.label.font= [UIFont fontWithName:#"Helvetica-Bold" size:20];
self.label.textColor = [UIColor colorWithRed:33.0f/255.0f green:74.0f/255.0f blue:146.0f/255.0f alpha:1.0f];
self.label.numberOfLines = 0;
self.label.lineBreakMode = NSLineBreakByWordWrapping;
self.label.backgroundColor = [UIColor whiteColor];
[self.contentView addSubview:self.label];
self.description = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 380.0, 300, 400)];
self.description.font= [UIFont fontWithName:#"Helvetica-Light" size:15];
self.description.textColor = [UIColor blackColor];
self.description.textAlignment = NSTextAlignmentJustified;
self.description.numberOfLines = 0;
self.description.lineBreakMode = NSLineBreakByWordWrapping;
self.description.backgroundColor = [UIColor whiteColor];
[self.description sizeToFit];
[self.contentView addSubview:self.description];
self.image = [[UIImageView alloc] initWithFrame:CGRectMake(20, 130, 280, 228)];
self.image.clipsToBounds = YES;
//[scrollView addSubview:self.image];
[self.contentView addSubview:self.image];
self.backgroundColor = [UIColor whiteColor];
I passed the data using this method from a different controller
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
Cell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
NSDictionary *item = [_articleListmain objectAtIndex:indexPath.item];
// set the article image
[cell.image setImageWithURL:[item objectForKey:#"image"]];
[cell.label setText:[item objectForKey:#"title"]];
[cell.description setText:[item objectForKey:#"description"]];
return cell;
}
Since the label is empty, sizeToFit shrinks it down to nothing. That's the point. Set some text then call sizeToFit and the label will be just big enough for the text.
I encountered the same problem. I have a customized cell and a separated tableview controller. it turns out that we should set the NumberOfLines and SizeToFit in the controller, not the cell.

IOS collection View creating cell images from core data and using GCD

I was trying to load cells for Collection view by using GCD to solve performance issue.
My codes for the loading of cells are as follows:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *slideCell =
[collectionView dequeueReusableCellWithReuseIdentifier:slideCellIdentifier
forIndexPath:indexPath];
slideCell.backgroundColor = [UIColor lightGrayColor];
slideCell.selectedBackgroundView = [[UIView alloc]initWithFrame:slideCell.bounds];
slideCell.selectedBackgroundView.backgroundColor = [UIColor redColor];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
#autoreleasepool {
SlideHeader *slideHeader = [self.fetchedResultsController objectAtIndexPath:indexPath];
UIImageView *imageView = [[UIImageView alloc] init];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
imageView.frame = CGRectMake(2, 2, slideCell.bounds.size.width-4, slideCell.bounds.size.height -4);
if (slideHeader.frontCoverImage) {
NSData *frontCoverImage = slideHeader.frontCoverImage;
imageView.image = [UIImage imageWithData:frontCoverImage];
}
dispatch_async(dispatch_get_main_queue(), ^{
NSArray *visibleCells = [self.collectionView visibleCells];
if ([visibleCells containsObject:slideCell]) {
[slideCell.contentView addSubview:imageView];
if (slideHeader.slideTitle.length > 0) {
UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(slideCell.bounds.origin.x, slideCell.bounds.size.height - 30, slideCell.bounds.size.width, 30)];
titleLabel.text = slideHeader.slideTitle;
titleLabel.backgroundColor = [UIColor lightTextColor];
titleLabel.font = [UIFont boldSystemFontOfSize:18];
titleLabel.textColor = [UIColor blackColor];
titleLabel.textAlignment = UITextAlignmentCenter;
titleLabel.userInteractionEnabled = NO;
[slideCell.contentView addSubview:titleLabel];
}
}
});
}
});
return slideCell;
}
I am using ARC and built in 6.1.
I believe that arc will hanld GCD memory release for me but I ended up with a problem:
Following is a screen shot of the memory use:
The momory went up as I scroll the collection view up and down continuesly.
I took a long time for the memory to get released and this causes the program to crash when the memory usage is high enough.
I tried to add autorealse in the GCD block as in my codes but this does not help releasing the memory quicker.
Can I ask what I can do to solve this issue? Thank you.
I solve the problem by changing the GCD block as follows:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
#autoreleasepool {
NSData *frontCoverImage;
if (slideHeader.frontCoverImage) {
frontCoverImage = slideHeader.frontCoverImage;
}
dispatch_async(dispatch_get_main_queue(), ^{
NSArray *visibleCells = [self.collectionView visibleCells];
if ([visibleCells containsObject:slideCell]) {
imageView.image = [UIImage imageWithData:frontCoverImage];
[slideCell.contentView addSubview:imageView];
if (slideHeader.slideTitle.length > 0) {
UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(slideCell.bounds.origin.x, slideCell.bounds.size.height - 30, slideCell.bounds.size.width, 30)];
titleLabel.text = slideHeader.slideTitle;
titleLabel.backgroundColor = [UIColor lightTextColor];
titleLabel.font = [UIFont boldSystemFontOfSize:18];
titleLabel.textColor = [UIColor blackColor];
titleLabel.textAlignment = UITextAlignmentCenter;
titleLabel.userInteractionEnabled = NO;
[slideCell.contentView addSubview:titleLabel];
}
}
});
}
});

Resources