CALayer memory leak - ios

Hoping someone can help me here because I'm losing the will to live with this memory issue.
When I push a particular view controller, Instruments shows a growth of around 3MB with the majority coming from CALayer objects belonging to each control I have on the view controller (mostly textfields and labels).
When I pop this view controller these CALayer allocations remain in memory, in fact every time I push and pop the controller I get a growth of 3MB each time.
So my question is how do I remove these from memory, is there something I need to be doing when deallocating the controller? The only reference in my code to the controls' layer is to create rounded corners and a border width (layer.cornerRadius = 10) but I still get the growth even when I comment this out.
The controller contains a tableview where each cell contains 3 textfields, 2 buttons and an imageview which are created programatically.
-(UIButton*) formatButton:(UIButton*)button
{
button.layer.cornerRadius = 10;
button.clipsToBounds = YES;
button.layer.borderColor=[[UIColor lightGrayColor] CGColor];
button.layer.borderWidth=1.0;
[button.titleLabel setTextAlignment:NSTextAlignmentCenter];
[button.titleLabel setFont:[UIFont fontWithName:#"HelveticaNeue-UltraLight" size:20]];
[button setTitle:#"0" forState:UIControlStateNormal];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
return button;
}
-(UITextField*)formatTextField:(UITextField*)textField
{
[textField setFont:[UIFont fontWithName:#"HelveticaNeue-UltraLight" size:20]];
textField.backgroundColor=[UIColor whiteColor];
textField.layer.borderColor=[[UIColor lightGrayColor] CGColor];
textField.layer.cornerRadius = 10;
textField.layer.borderWidth=1.0;
[textField setTextAlignment:NSTextAlignmentCenter];
textField.clipsToBounds=YES;
textField.text=#"";
textField.enabled=NO;
return textField;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ItemCellID" forIndexPath:indexPath];
// Configure the cell...
OrderedProduct *orderedProduct=self.orderedProductsArray[indexPath.row];
//NSLog (#"ordered Product %#",orderedProduct.productID);
UITextField *qualityField=[[UITextField alloc] initWithFrame:CGRectMake(113,23,324,30)];
qualityField=[self formatTextField:qualityField];
[cell addSubview:qualityField];
UITextField *sizeField=[[UITextField alloc] initWithFrame:CGRectMake(445, 24, 142, 30)];
sizeField=[self formatTextField:sizeField];
[cell addSubview:sizeField];
UITextField *totalPriceField=[[UITextField alloc] initWithFrame:CGRectMake(786,24,137,30)];
totalPriceField=[self formatTextField:totalPriceField];
[cell addSubview:totalPriceField];
UIButton *quantityButton=[[UIButton alloc] initWithFrame:CGRectMake(595,24,60,30)];
quantityButton=[self formatButton:quantityButton];
[cell addSubview:quantityButton];
UIButton *priceButton=[[UIButton alloc] initWithFrame:CGRectMake(663,24,119,30)];
priceButton=[self formatButton:priceButton];
[cell addSubview:priceButton];
UIImageView *imageView=[[UIImageView alloc] initWithFrame:CGRectMake(5,15,100,50)];
[cell addSubview:imageView];
UIButton *removeButton=(UIButton*)[cell viewWithTag:kRemoveButton];
if (self.selectedOrder.status==[NSNumber numberWithInt:kOrderStatusProvisional])
{
quantityButton.enabled=YES;
quantityButton.backgroundColor=[Settings getInstance].enabledButtonColor;
[quantityButton addTarget:self action:#selector(quantityButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
priceButton.enabled=YES;
priceButton.backgroundColor=[Settings getInstance].enabledButtonColor;
removeButton.hidden=NO;
[removeButton addTarget:self action:#selector(removeButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
}
else
{
quantityButton.enabled=NO;
quantityButton.backgroundColor=[Settings getInstance].disabledButtonColor;
priceButton.enabled=NO;
priceButton.backgroundColor=[Settings getInstance].disabledButtonColor;
removeButton.hidden=YES;
}
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setCurrencyCode:#"GBP"];
[numberFormatter setNumberStyle: NSNumberFormatterCurrencyStyle];
imageView.image=[self.imageCache objectForKey:orderedProduct.product.productImageName];
UITapGestureRecognizer *tgr=[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageViewTapped:)];
imageView.userInteractionEnabled=YES;
[imageView addGestureRecognizer:tgr];
qualityField.text=orderedProduct.product.name;
sizeField.text=orderedProduct.product.productSize.productSize;
quantityButton.titleLabel.text=[NSString stringWithFormat:#"%#",orderedProduct.quantity];
[quantityButton setTitle:[NSString stringWithFormat:#"%#",orderedProduct.quantity] forState:UIControlStateNormal];
float price=[orderedProduct.price integerValue]/100; // server price is in pennies
float totalPrice=price*[orderedProduct.quantity integerValue];
[priceButton setTitle:[numberFormatter stringFromNumber:[NSNumber numberWithFloat:price]] forState:UIControlStateNormal];
totalPriceField.text=[numberFormatter stringFromNumber:[NSNumber numberWithFloat:totalPrice]];
return cell;
}
Not able to post images yet so below is a crude description of what Instruments is saying,
Snapshot Growth
Generation B 3.64MB
VM: UILabel (CALayer) 964KB
VM: UITextFieldLabel (CALayer) 792KB
VM: CoreAnimation 788KB

Related

How to create n number of UIButton programmatically in UITableView Cell?

I am trying to create one UITableView with n number of buttons depends on backend JSON data.
I have attached an image, i know how to create UIButtons on UITableViewCell but i don't know how to place them correctly inside UITableViewCell.
UIButton for UITableViewCell
UIButton *continuebtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 100, view1.frame.size.width-20, 40)];
[continuebtn setBackgroundColor:[UIColor grayColor]];
[continuebtn setTitle:#"Continue" forState:UIControlStateNormal];
continuebtn.layer.cornerRadius = 10;
continuebtn.layer.borderWidth =1.0;
continuebtn.layer.borderColor = [UIColor blackColor].CGColor;
[continuebtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
How to place 'n' number of UIButton on UITableViewCell ?? UIButton width depends on its text content
If you want to put buttons vertically in a cell, use following suggestions:
Your UITableviewCell's height would depend upon number of buttons. Implement heightForRowAtIndexPath method as following:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 100.0f + (buttonsArray.count*buttonHeight+buttonsHeightSeparator);
//change 100.0f with height that is required for cell without buttons
//buttonHeight is a static float representing value for height of each button
//buttonHeightSeparator is a static float representing separation distance between two buttons
}
In your cellForRowAtIndexPath method, you can create buttons using following code:
for(int i=0; i<buttonsArray.count; i++) {
UIButton *continuebtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 100+i*(buttonHeight+buttonsHeightSeparator), view1.frame.size.width-20, 40)];
[continuebtn setBackgroundColor:[UIColor grayColor]];
[continuebtn setTitle:#"Continue" forState:UIControlStateNormal];
continuebtn.layer.cornerRadius = 10;
continuebtn.layer.borderWidth =1.0;
continuebtn.layer.borderColor = [UIColor blackColor].CGColor;
[continuebtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[continuebtn addTarget:self action:#selector(continueBtnPressed:) forControlEvents:UIControlEventTouchUpInside]; //add target to receive button tap event
[continuebtn setTag:i]; //to identify button
[cell.contentView addSubview:continuebtn]; //add button to cell
}
I have found a better answer myself.
Please check this code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
[cell addSubview:[self addView:indexPath.row]];
return cell;
}
-(UIView *)addView:(NSInteger)row{
UIView *progView;
progView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,cell.frame.size.width,cell.frame.size.height)];
progView.backgroundColor = [UIColor grayColor];
progView.tag = i;
progView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
int x,y;
x=10;y=10;
for(int i=0;i<10;i++){
UIButton *button = [[UIButton alloc]init];
NSString *myString=#"Dynamic";
[button setTitle:myString forState:UIControlStateNormal];
CGSize stringsize = [myString sizeWithFont:[UIFont systemFontOfSize:14]];
[button setFrame:CGRectMake(x,y,stringsize.width+40, stringsize.height+20)];
x+=stringsize.width+50;
NSLog(#"%d-%f",x,progView.frame.size.width);
if(x>progView.frame.size.width){
y+=50;
x=10;
}
button.layer.borderWidth =1.0;
button.layer.borderColor = [UIColor greenColor].CGColor;
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button setTag:i];
[progView addSubview:button];
}
return progView;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 200;
}

unwanted white space "under" tableView subview when tableView scrolled to its content limits

I have a UITableViewCell as a subview in a custom view controller. It works great except that when it scrolls to its top or bottom of its contentSize limit, it "keeps going" and leaves some white space exposed behind it. This is particularly irritating because I do have a UIView covering the entire screen behind the tableView, and that view is set to a non-white color. I also added a subview exactly underlaying the tableview with the same background color, again attempting to block the white. I also set the UIApplication Window background color to a non white color. None of this worked.
I would have thought that even if my TableView bounces around its origin frame, the "exposed" view should match the underlying view rather than be white. How can I fix my tableView so that it retains all its scroll properties but doesn't reveal white when it bounces around at the end of a scroll?
Here is a screen shot of the effect. The white appears the tableViewHeader and below a UISCrollView that occupies the top of the screen. This appears when I scroll the tableView all the way to one extreme. The white space appears at the bottom rather than the top of the tableView if I scroll all the way to the other end.
Here's the relevant code, quite vanilla I think:
#interface JudgeViewController () <UITextFieldDelegate, UITextViewDelegate, UINavigationControllerDelegate, UIGestureRecognizerDelegate, UITableViewDataSource, UITableViewDelegate, UIViewControllerRestoration, UIScrollViewDelegate>
#property (nonatomic) UITableView *tableView;
#end
functions to set tableViewCells
#pragma mark - tableview appearance and actions
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
StatsViewController *svc = [[StatsViewController alloc] init];
svc.user = self.object.answerUser[indexPath.row];
svc.fromJudge = YES;
[self.navigationController pushViewController:svc animated:YES];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.object.answerArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
UILabel *label = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(cell ==nil)
{
cell = [[UITableViewCell alloc] initWithFrame:CGRectZero];
label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setLineBreakMode: UILineBreakModeWordWrap];
[label setMinimumFontSize:SMALL_FONT_SIZE];
[label setNumberOfLines:0];
[label setFont:[UIFont systemFontOfSize:SMALL_FONT_SIZE]];
[label setTag:1];
// [[label layer] setBorderWidth:2.0f];
[[cell contentView] addSubview:label];
}
CGFloat width = [[UIScreen mainScreen] bounds].size.width;
CGFloat height = [[UIScreen mainScreen] bounds].size.height;
NSString *text = self.object.answerArray[indexPath.row];
CGSize constraint = CGSizeMake(.8*CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN)*2, 200000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:SMALL_FONT_SIZE] constrainedToSize:constraint];
if(!label)
label = (UILabel *)[cell viewWithTag:1];
[label setText:text];
[label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, .8*CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN)*2, MAX(size.height, 44.0f))];
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button1.frame = CGRectMake(.85*width, label.frame.size.height/2-2*CELL_CONTENT_MARGIN, .12*width, 20);
[button1 setTitle:#"UP" forState:UIControlStateNormal];
button1.titleLabel.font =[UIFont systemFontOfSize:SMALLEST_FONT_SIZE];
[button1 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button1 addTarget:self action:#selector(upVoteA:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button1];
[cell.contentView bringSubviewToFront:button1];
UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button2.frame = CGRectMake(.85*width, label.frame.size.height/2+2*CELL_CONTENT_MARGIN, .12*width, 20);
[button2 setTitle:#"DOWN" forState:UIControlStateNormal];
button2.titleLabel.font =[UIFont systemFontOfSize:SMALLEST_FONT_SIZE];
[button2 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button2 addTarget:self action:#selector(downVoteA:) forControlEvents:UIControlEventTouchUpInside];
CGFloat moduloResult = indexPath.row % 2;
if(moduloResult>0)
{
cell.backgroundColor = [UIColor colorWithRed:1 green:0.647 blue:0 alpha:.6];
}
else
{
cell.backgroundColor = [UIColor colorWithRed:1 green:0.647 blue:0 alpha:.4];
}
cell.opaque = NO;
cell.alpha = 0.2;
[cell.contentView addSubview:button2];
[cell.contentView bringSubviewToFront:button2];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
-(void)keyboardToJudge
{
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row < [self.object.answerArray count])
{
NSString *text = self.object.answerArray[indexPath.row];
CGSize constraint = CGSizeMake(.8*CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN)*2, 200000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE-2.0f] constrainedToSize:constraint];
CGFloat height = MAX(size.height, 44.0f);
return height + (CELL_CONTENT_MARGIN)*2;
}
else
{
return 200.0f;
}
}
functions setting out layout:
-(void)viewDidLoad
{
...among other things setting up top scroll view (top part of view with gray background and orange text)...
if(self.navigationController.navigationBar.frame.size.height>0)
{
self.scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 5, width, height*SCROLL_VIEW_OFFSET)];
}
else
{
self.scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, statusBarHeight+5, width, height*SCROLL_VIEW_OFFSET)];
}
self.scroll.backgroundColor = BACKGROUND_COLOR;
self.scroll.contentSize =CGSizeMake(width, .5*height);
self.scroll.delegate = self;
self.scroll.contentInset = UIEdgeInsetsMake(30, 0, 30, 0);
[self.scroll setShowsHorizontalScrollIndicator:NO];
...adding buttons to self.scroll...
[self.view addSubview:self.scroll];
....
self.tableView = [[UITableView alloc] initWithFrame:frame];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _width, _height*.1)];
self.tableView.tableFooterView.backgroundColor = BACKGROUND_COLOR;
self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _width, _height*.1)];
self.tableView.tableHeaderView.backgroundColor = BACKGROUND_COLOR;
....tableView hidden state is changed to yes in another function if row count is zero but not usually...
self.tableView.hidden = NO;
[self.view addSubview:self.tableView];
...
}
Finally, I also call :
[self.tableView reloadData];
after reloading data from a webserver and depending on the results either set the tableView to hidden or not (not hidden if there are results to display). That should be every line of code that touches the tableView subview.
Add to your viewDidLoad
[self.tableView setBackgroundColor:BACKGROUND_COLOR];
Set the background color of your tableView and you'll be fine
Change this line:
self.scroll.contentInset = UIEdgeInsetsMake(30, 0, 30, 0);
To this:
self.scroll.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
You are adding a footer to your tableview with that line. The following image is from the IOS dev Library
Set the table view estimate to 0 (Uncheck Automatic) in the size inspector

UITableview slow scroll and increase ram after some scrolls

this is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"hourCell" forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text=hoursarray[indexPath.row];
if ([cell.contentView subviews]){
for (UIView *subview in [cell.contentView subviews]) {
[subview removeFromSuperview];
}
}
UIButton *buttonOff = [UIButton buttonWithType:UIButtonTypeCustom];
buttonOff.layer.cornerRadius = 5.0f;
UIButton *buttonT1 = [UIButton buttonWithType:UIButtonTypeCustom];
buttonT1.layer.cornerRadius = 5.0f;
UIButton *buttonT2 = [UIButton buttonWithType:UIButtonTypeCustom];
buttonT2.layer.cornerRadius = 5.0f;
buttonOff.frame = CGRectMake(130, 5, 40, 34);
[buttonOff setTitle:#"OFF" forState:UIControlStateNormal];
[buttonOff addTarget:self action:#selector(onButtonOFFTap:) forControlEvents:UIControlEventTouchUpInside];
buttonT1.frame = CGRectMake(190, 5, 40, 34);
[buttonT1 setTitle:#"T1" forState:UIControlStateNormal];
[buttonT1 addTarget:self action:#selector(onButtonT1Tap:) forControlEvents:UIControlEventTouchUpInside];
buttonT2.frame = CGRectMake(250, 5, 40, 34);
[buttonT2 setTitle:#"T2" forState:UIControlStateNormal];
[buttonT2 addTarget:self action:#selector(onButtonT2Tap:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:buttonOff];
[cell.contentView bringSubviewToFront:buttonOff];
buttonOff.tag=indexPath.row;
[cell addSubview:buttonT1];
[cell.contentView bringSubviewToFront:buttonT1];
buttonT1.tag=indexPath.row;
[cell.contentView bringSubviewToFront:buttonT2];
[cell addSubview:buttonT2];
buttonT2.tag=indexPath.row;
if([[NSString stringWithFormat:#"%#",[datiProgrTemp objectAtIndex:indexPath.row+48*day]] isEqual:#"1"])
{
buttonOff.backgroundColor = [UIColor greenColor];
buttonT1.backgroundColor = [UIColor lightGrayColor];
buttonT2.backgroundColor = [UIColor lightGrayColor];
}
if([[NSString stringWithFormat:#"%#",[datiProgrTemp objectAtIndex:indexPath.row+48*day]] isEqual:#"2"])
{
buttonOff.backgroundColor = [UIColor lightGrayColor];
buttonT1.backgroundColor = [UIColor greenColor];
buttonT2.backgroundColor = [UIColor lightGrayColor];
}
if([[NSString stringWithFormat:#"%#",[datiProgrTemp objectAtIndex:indexPath.row+48*day]] isEqual:#"3"])
{
buttonOff.backgroundColor = [UIColor lightGrayColor];
buttonT1.backgroundColor = [UIColor lightGrayColor];
buttonT2.backgroundColor = [UIColor greenColor];
}
return cell;
}
The fact is that after two or three scrolls (fast and smooth) the scrolling goes slow and crappy and the ram used increase.
I tried to put if(cell==nill) but I'm using storyboard and the cell is never nill
Am I wrong in something?
Thanks a lot,
N.
There are a couple problems here.
The whole point of using dequeueReusableCellWithIdentifier: is to reuse your cells and their content. But I see you've used this line:
if ([cell.contentView subviews]){
for (UIView *subview in [cell.contentView subviews]) {
[subview removeFromSuperview];
}
}
to remove the cell content at every call to cellForRowAtIndexPath:. This is a waste of using dequeueReusableCellWithIdentifier:.
Nevertheless, your logic is almost correct. You can remove the subviews and create new subviews without having the incremental memory issues you're describing. The problem is you've made a small error:
You're adding the UIButtons directly to the cell's view, for example
[cell addSubview:buttonOff];
but removing the subviews of the cell's content view:
[cell.contentView subviews]
(You're also using bringSubviewToFront: ineffectively for this same reason.)
Because of this mistake, you're not actually removing the buttons at every call to cellForRowAtIndexPath: as you've intended so as you scroll back and forth, buttons are being added one on top of another on top of another, thus increasing memory usage.
To fix this problem, whether you add and remove from cell or cell.contentView, you have to be consistent.
All that aside though, since the content of your cells is very similar, I highly recommend you use dequeueReusableCellWithIdentifier: in the way it was intended by actually reusing your cells' content.
Thanks to all. This is the code working good. I added a TableViewCell class that contains only the outlet to the buttons (added buttons graphically in the storyboard):
#import <UIKit/UIKit.h>
#interface CHRTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIButton *buttonOFF;
#property (weak, nonatomic) IBOutlet UIButton *buttonT1;
#property (weak, nonatomic) IBOutlet UIButton *buttonT2;
#end
then instantiated cell on tableview controller and pointing to the outlet changed the button's aspect:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CHRTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"hourCell" forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text=hoursarray[indexPath.row];
cell.buttonOFF.layer.borderColor = [UIColor lightGrayColor].CGColor;
cell.buttonOFF.layer.borderWidth = 0.5f;
cell.buttonOFF.layer.cornerRadius = 5.0f;
cell.buttonT1.layer.borderColor = [UIColor lightGrayColor].CGColor;
cell.buttonT1.layer.borderWidth = 0.5f;
cell.buttonT1.layer.cornerRadius = 5.0f;
cell.buttonT2.layer.borderColor = [UIColor lightGrayColor].CGColor;
cell.buttonT2.layer.borderWidth = 0.5f;
cell.buttonT2.layer.cornerRadius = 5.0f;
[cell.buttonOFF setTitle:#"OFF" forState:UIControlStateNormal];
[cell.buttonOFF addTarget:self action:#selector(onButtonOFFTap:) forControlEvents:UIControlEventTouchUpInside];
[cell.buttonT1 setTitle:#"T1" forState:UIControlStateNormal];
[cell.buttonT1 addTarget:self action:#selector(onButtonT1Tap:) forControlEvents:UIControlEventTouchUpInside];
[cell.buttonT2 setTitle:#"T2" forState:UIControlStateNormal];
[cell.buttonT2 addTarget:self action:#selector(onButtonT2Tap:) forControlEvents:UIControlEventTouchUpInside];
cell.buttonOFF.tag=indexPath.row;
cell.buttonT1.tag=indexPath.row;
cell.buttonT2.tag=indexPath.row;
if([[NSString stringWithFormat:#"%#",[datiProgrTemp objectAtIndex:indexPath.row+48*day]] isEqual:#"1"])
{
cell.buttonOFF.backgroundColor = [UIColor colorWithRed:0.0f/255.0f green:200.0f/255.0f blue:60.0f/255.0f alpha:1.0f];
cell.buttonT1.backgroundColor = [UIColor whiteColor];
cell.buttonT2.backgroundColor = [UIColor whiteColor];
}
if([[NSString stringWithFormat:#"%#",[datiProgrTemp objectAtIndex:indexPath.row+48*day]] isEqual:#"2"])
{
cell.buttonOFF.backgroundColor = [UIColor whiteColor];
cell.buttonT1.backgroundColor = [UIColor colorWithRed:0.0f/255.0f green:200.0f/255.0f blue:60.0f/255.0f alpha:1.0f];;
cell.buttonT2.backgroundColor = [UIColor whiteColor];
}
if([[NSString stringWithFormat:#"%#",[datiProgrTemp objectAtIndex:indexPath.row+48*day]] isEqual:#"3"])
{
cell.buttonOFF.backgroundColor = [UIColor whiteColor];
cell.buttonT1.backgroundColor = [UIColor whiteColor];
cell.buttonT2.backgroundColor = [UIColor colorWithRed:0.0f/255.0f green:200.0f/255.0f blue:60.0f/255.0f alpha:1.0f];;
}
return cell;
}

Delay introduced while presenting UIViewController

I am developing application in which I am presenting new UIViewController from another using [self performSegueWithIdentifier:#"newViewSegue" sender:self];
In new UIViewController I am initialising my view elements and adding UITableView programmatically to it.
But when I call this performSegueWithIdentifier new UIViewController is displayed after some delay, I tried to put log in viewDidLoad of new UIViewController and before [self performSegueWithIdentifier:#"newViewSegue" sender:self]; statement both statements are executed immediately but view is displayed after some interval.
My ViewDidLoad method is as follow:
-(void)viewDidLoad{
sharedObject=[SingleToneClass sharedManager];
selectedButtonTag=-1;
initFlag=0;
NSLog(#"End %#",[NSDate date]);
backgroundView.backgroundColor=[self hexToUiColor:#"E7E7E7"];
[mondayDateButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
//set colour for all 7days buttons
[mondayDateButton.titleLabel setFont:[UIFont boldSystemFontOfSize:14]];
//Set font for all days button
[mondayButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
//set title colour
[mondayButton.titleLabel setFont:[UIFont systemFontOfSize:12]];
//set font
//Changing image Color
//Home Button
[homeButton.titleLabel setFont:[UIFont fontWithName:kFontAwesomeFamilyName size:40]];
[homeButton setTitleColor:[self hexToUiColor:sharedObject.secondaryHexColorCode] forState:UIControlStateNormal];
[homeButton setTitle:[NSString fontAwesomeIconStringForIconIdentifier:#"fa-home"] forState:UIControlStateNormal];
//Back Button
[backButton.titleLabel setFont:[UIFont fontWithName:kFontAwesomeFamilyName size:27]];
[backButton setTitleColor:[self hexToUiColor:sharedObject.secondaryHexColorCode] forState:UIControlStateNormal];
[backButton setTitle:[NSString fontAwesomeIconStringForIconIdentifier:#"fa-chevron-left"] forState:UIControlStateNormal];
//Next Week Button
[nextWeek.titleLabel setFont:[UIFont fontWithName:kFontAwesomeFamilyName size:20]];
[nextWeek setTitleColor:[self hexToUiColor:sharedObject.secondaryHexColorCode] forState:UIControlStateNormal];
[nextWeek setTitle:[NSString fontAwesomeIconStringForIconIdentifier:#"fa-chevron-right"] forState:UIControlStateNormal];
//Previous Week Button
[previousWeek.titleLabel setFont:[UIFont fontWithName:kFontAwesomeFamilyName size:20]];
[previousWeek setTitleColor:[self hexToUiColor:sharedObject.secondaryHexColorCode] forState:UIControlStateNormal];
[previousWeek setTitle:[NSString fontAwesomeIconStringForIconIdentifier:#"fa-chevron-left"] forState:UIControlStateNormal];
[separatorLineView setBackgroundColor:[self hexToUiColor:#"6D6D6D"]];
[selectLabel setTextColor:[self hexToUiColor:#"6D6D6D"]];
[selectLabel setFont:[UIFont boldSystemFontOfSize:13]];
selectLabel.text=[NSString stringWithFormat:#"%#",selectedTitle];
sharedObject.bookADateTitle=selectedTitle;
//make Buttons Rounded
mondayDateButton.clipsToBounds = YES;
mondayDateButton.layer.cornerRadius = mondayDateButton.frame.size.height/2;
NSDate *currentDate;
if (sharedObject.bookDateViewDate.length>0) {
NSDateFormatter *dateFormat1 = [[NSDateFormatter alloc] init];
[dateFormat1 setDateFormat:#"yyyy-MM-dd"];
currentDate=[dateFormat1 dateFromString:sharedObject.bookDateViewDate];
}
else{
currentDate=[NSDate date];
}
[self setDate:currentDate];
[self setDateToLabel:currentDate]; //set formatted date
//create and initialise UITableView
static NSString *cellIdentifier=#"CustomHiddenViewCell";
CustomHiddenViewCell *cell = (CustomHiddenViewCell *)[slotsTableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomHiddenViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
double heightOfTable=(self.view.frame.size.height-backgroundView.frame.size.height);
//creating tableview1
slotsTableView=[[UITableView alloc]initWithFrame:CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y+backgroundView.frame.size.height,self.view.frame.size.width,heightOfTable)];
slotsTableView.scrollEnabled=YES;
slotsTableView.delegate=self;
[slotsTableView flashScrollIndicators];
slotsTableView.dataSource=self;
slotsTableView.bounces=NO;
slotsTableView.showsVerticalScrollIndicator=YES;
slotsTableView.separatorStyle=UITableViewCellSeparatorStyleNone;
[self.view addSubview:slotsTableView];
//add swipe gesture
UISwipeGestureRecognizer *leftSwipRecognizer;
leftSwipRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(SwipeRecognizer:)];
[leftSwipRecognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[slotsTableView addGestureRecognizer:leftSwipRecognizer];
UISwipeGestureRecognizer *rightSwipRecognizer;
rightSwipRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(SwipeRecognizer:)];
[rightSwipRecognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[slotsTableView addGestureRecognizer:rightSwipRecognizer];
[leftWeekRecognizer addTarget:self action:#selector(WeekSwipeRecognizer:)];
[leftWeekRecognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[rightWeekRecognizer addTarget:self action:#selector(WeekSwipeRecognizer:)];
[rightWeekRecognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
}
Can anyone tell me why this delay is introduced?
May be your code is executing in other then main thread, move your code in main thread or use GCD like
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
});

IOS UITableview Scroll is not smooth in IOS6

And I complete IOS app in IOS 7 and its works fine IOS 7 and then I start converting my app to IOS 6 I face lot of problems.After a huge struggle I rectify almost all the issuse other that Performance issue
I am using UITableview to display all the contents and when I test my app in Iphone 5c there is no problem in scrolling the table view. And the I test my app in ipod retina list is not scrolling smoothly. It is one of the huge problem for me and also Its killing my time
To illustrate my issue I have added my tableview cell code below. Please Suggest me some quick solution
UITableviewCell Code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellidentifier=#"cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellidentifier];
if (cell ==nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier]autorelease];
}
[[cell.contentView subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
cell.selectionStyle = UITableViewCellEditingStyleNone;
UIView * contentview = [[[UIView alloc]init]autorelease];
UIImageView * userimage = [[[UIImageView alloc]init]autorelease];
UIImageView * itemimageview = [[[UIImageView alloc]init]autorelease];
UIView * bottomview = [[[UIView alloc]init]autorelease];
UILabel * imagenameLable = [[[UILabel alloc]init]autorelease];
UILabel * usernameLable = [[[UILabel alloc]init]autorelease];
UILabel * itemcostLable = [[[UILabel alloc]init]autorelease];
UIButton*fancybtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIButton * addrditbtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIButton * commentBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UILabel * noofcommentsLable = [[[UILabel alloc]init]autorelease];
// [contentBgImageview setImage:[UIImage imageNamed:#"item_bg.png"]];
[itemimageview setAutoresizesSubviews:YES];
// [itemimageview setContentMode:UIViewContentModeScaleAspectFill];
[itemimageview setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",[[[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"photos"]objectAtIndex:0]objectForKey:#"item_url_main_350"]]]];
[itemimageview setContentMode:UIViewContentModeScaleAspectFit];
[itemimageview setTag:indexPath.row];
[userimage setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",[[[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"photos"]objectAtIndex:0]objectForKey:#"user_url_main_70"]]]];
[bottomview setBackgroundColor:[UIColor colorWithRed:200/255 green:54/255 blue:54/255 alpha:0.4]];
[bottomview setBackgroundColor:[UIColor colorWithRed:255 green:255 blue:255 alpha:1]];
// [bottomview setAlpha:0.5];
[imagenameLable setText:[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"item_title"]];
[imagenameLable setTextColor:[UIColor blackColor]];
[imagenameLable setFont:[UIFont fontWithName:#"Helvetica-Bold" size:14]];
[imagenameLable setBackgroundColor:[UIColor clearColor]];
[bottomview addSubview:imagenameLable];
[usernameLable setText:[NSString stringWithFormat:#"#%#",[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"sellername"]]];
[usernameLable setTextColor:[UIColor grayColor]];
[usernameLable setFont:[UIFont fontWithName:#"Helvetica" size:10]];
[usernameLable setBackgroundColor:[UIColor clearColor]];
[bottomview addSubview:usernameLable];
[itemcostLable setText:[NSString stringWithFormat:#"%# %#",delegate.currencyStr,[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"price"]]];
[itemcostLable setTextColor:[UIColor grayColor]];
[itemcostLable setFont:[UIFont fontWithName:#"Helvetica-Bold" size:16]];
[itemcostLable setBackgroundColor:[UIColor clearColor]];
[bottomview addSubview:itemcostLable];
// [addrditbtn setImage:[UIImage imageNamed:#"add.png"] forState:UIControlStateNormal];
if ([[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"liked"]isEqualToString:#"No"])
{
[fancybtn setImage:[UIImage imageNamed:#"fantacybtn.png"] forState:UIControlStateNormal];
[addrditbtn setImage:[UIImage imageNamed:#"addtolist.png"] forState:UIControlStateNormal];
}
else
{
[fancybtn setImage:[UIImage imageNamed:#"fantacydbtn.png"] forState:UIControlStateNormal];
[addrditbtn setImage:[UIImage imageNamed:#"addtolist.png"] forState:UIControlStateNormal];
}
NSString*itemid=[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"id"];
if ([delegate.fantacyitemsArray containsObject:itemid]) {
[fancybtn setImage:[UIImage imageNamed:#"fantacydbtn.png"] forState:UIControlStateNormal];
[addrditbtn setImage:[UIImage imageNamed:#"addtolist.png"] forState:UIControlStateNormal];
}
if ([delegate.unfantacyitemsArray containsObject:itemid]) {
[fancybtn setImage:[UIImage imageNamed:#"fantacybtn.png"] forState:UIControlStateNormal];
[addrditbtn setImage:[UIImage imageNamed:#"addtolist.png"] forState:UIControlStateNormal];
}
fancybtn.tag=[itemid intValue];
[fancybtn addTarget:self action:#selector(fancyBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
addrditbtn.tag=[itemid intValue];
[addrditbtn addTarget:self action:#selector(addtolistBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
[commentBtn setImage:[UIImage imageNamed:#"commentnew.png"] forState:UIControlStateNormal];
[commentBtn setUserInteractionEnabled:YES];
commentBtn.tag=indexPath.row;
[commentBtn addTarget:self action:#selector(commentBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
UIButton * usernameBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[usernameBtn setUserInteractionEnabled:YES];
usernameBtn.tag=indexPath.row;
[usernameBtn addTarget:self action:#selector(usernameBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
[noofcommentsLable setTextColor:[UIColor grayColor]];
[noofcommentsLable setFont:[UIFont fontWithName:#"Helvetica" size:12]];
int commentcount = 0;
if([delegate.newaddedcommentDict objectForKey:[NSString stringWithFormat:#"%#Array",[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"id"]]])
{
commentcount = [[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"commentcount"]intValue]+[[delegate.newaddedcommentDict objectForKey:[NSString stringWithFormat:#"%#Array",[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"id"]]]count];
}
else
{
commentcount = [[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"commentcount"]intValue];
}
[noofcommentsLable setText:[NSString stringWithFormat:#"%d",commentcount]];
UIScrollView * scroll = [[[UIScrollView alloc]init]autorelease];
// [scroll setScrollEnabled:NO];
[scroll setUserInteractionEnabled:YES];
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(gestureAction:)];
[recognizer setNumberOfTapsRequired:1];
scroll.userInteractionEnabled = YES;
[scroll addGestureRecognizer:recognizer];
[itemcostLable setTextAlignment:NSTextAlignmentRight];
[bottomview setFrame:CGRectMake(0,3,300,37)];
[itemimageview setFrame:CGRectMake(0,0,300,240)];
CGSize size;
if ([[[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"photos"]objectAtIndex:0]objectForKey:#"width"]!=[NSNull null]||[[[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"photos"]objectAtIndex:0]objectForKey:#"height"]!=[NSNull null])
{
size= [self aspectScaledImageSizeForImageView:itemimageview width:[[[[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"photos"]objectAtIndex:0]objectForKey:#"width"]floatValue] height:[[[[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"photos"]objectAtIndex:0]objectForKey:#"height"]floatValue]];
}
else
{
size = CGSizeMake(100,100);
}
[itemimageview setFrame:CGRectMake((300-size.width)/2,0,size.width,size.height)];
[scroll setFrame:CGRectMake(0,43,300,size.height)];
//place holder image
UIImageView * placeholderimageview = [[[UIImageView alloc]init]autorelease];
[placeholderimageview setFrame:CGRectMake(130,0,40,size.height)];
[placeholderimageview setImage:[UIImage imageNamed:#"57.png"]];
[placeholderimageview setContentMode:UIViewContentModeScaleAspectFit];
// [itemimageview setBackgroundColor:[UIColor redColor]];
[imagenameLable setFrame:CGRectMake(40,5,160,15)];
[usernameLable setFrame:CGRectMake(40,20,160,15)];
[usernameBtn setFrame:CGRectMake(0,5,200,30)];
[itemcostLable setFrame:CGRectMake(220,0,70,40)];
[fancybtn setFrame:CGRectMake(5,size.height+48,78,25)];
[commentBtn setFrame:CGRectMake(221,size.height+48,40,25)];
[noofcommentsLable setFrame:CGRectMake(240,size.height+48,20,25)];
[addrditbtn setFrame:CGRectMake(265,size.height+48,27,25)];
// [commentBtn setFrame:CGRectMake(191,size.height+48,40,25)];
// [noofcommentsLable setFrame:CGRectMake(211,size.height+48,20,25)];
// [addrditbtn setFrame:CGRectMake(236,size.height+48,27,25)];
// [cartbtn setFrame:CGRectMake(268,size.height+48,27,25)];
[contentview setFrame:CGRectMake(10,5,300,size.height+78)];
[userimage setFrame:CGRectMake(5,5,30,30)];
[scroll setBackgroundColor:[UIColor colorWithRed:0.976 green:0.976 blue:0.976 alpha:1]];
[scroll setBackgroundColor:[UIColor clearColor]];
contentview.clipsToBounds = NO;
contentview.layer.masksToBounds = NO;
contentview.layer.shadowColor = [[UIColor grayColor] CGColor];
contentview.layer.shadowOffset = CGSizeMake(0,1);
contentview.layer.shadowOpacity = 0.2;
contentview.layer.shadowRadius = 0.6;
contentview.layer.cornerRadius = 6.0; // set as you want.
[bottomview setBackgroundColor:[UIColor clearColor]];
userimage.layer.cornerRadius = 15.0;
userimage.layer.masksToBounds = YES;
[itemimageview setUserInteractionEnabled:YES];
[scroll setBackgroundColor:[UIColor clearColor]];
[bottomview setBackgroundColor:[UIColor clearColor]];
[contentview setBackgroundColor:[UIColor whiteColor]];
//place holder image
[contentview addSubview:scroll];
[scroll addSubview:placeholderimageview];
[scroll addSubview:itemimageview];
[contentview addSubview:bottomview];
[contentview addSubview:fancybtn];
[contentview addSubview:addrditbtn];
[contentview addSubview:commentBtn];
[contentview addSubview:noofcommentsLable];
[contentview addSubview:userimage];
[contentview addSubview:usernameLable];
[contentview addSubview:usernameBtn];
[cell.contentView addSubview:contentview];
[cell setBackgroundColor:[UIColor clearColor]];
[cell.contentView setBackgroundColor:[UIColor clearColor]];
// Configure the cell...
return cell;
}
Its because in every time when cellForRowAtIndexPath: method called you recreating all subviews again.
You must do it only once.
Make a class that inherits from UITableViewCell.
//MyCell.h file
#interface MyCell : UITableViewCell
//here declare all views that you need, e.g.
#property (strong, nonatomic) UILabel *imagenameLable;
#property (strong, nonatomic) UILabel *usernameLable;
// and so on. But only those, that you mast set value (or read values) outside of this class.
// the other views declare in MyClass.m file, so they are for private use (eg. contentview,etc...)
#end
//MyCell.m file
#interface MyCell()
// here declare private properties
#property (strong, nonatomic) UIView* contentview;
// and so on...
#end
#implementation
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self setupUI];
}
return self;
}
- (void)setupUI
{
//and finally, in this method build your views, i.e. allocate your views, add subview of this cell, set frames, font to labels, text colors, etc...
//e.g.
self.contentview = [[[UIView alloc]init]autorelease];
self.contentview.clipsToBounds = NO;
self.contentview.layer.masksToBounds = NO;
self.contentview.layer.shadowColor = [[UIColor grayColor] CGColor];
self.contentview.layer.shadowOffset = CGSizeMake(0,1);
self.contentview.layer.shadowOpacity = 0.2;
self.contentview.layer.shadowRadius = 0.6;
self.contentview.layer.cornerRadius = 6.0; // set as you want.
// initialize other views
[self.contentview addSubview:self.scroll];
[self.scroll addSubview:self.placeholderimageview];
[self.scroll addSubview:self.itemimageview];
[self.contentview addSubview:self.bottomview];
[self.contentview addSubview:self.fancybtn];
[self.contentview addSubview:self.addrditbtn];
[self.contentview addSubview:self.commentBtn];
[self.contentview addSubview:self.noofcommentsLable];
[self.contentview addSubview:self.userimage];
[self.contentview addSubview:self.usernameLable];
[self.contentview addSubview:self.usernameBtn];
[self.contentView addSubview:self.contentview];
// something like this.
}
#end
And finally
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellidentifier=#"cell";
MyCell *cell=[tableView dequeueReusableCellWithIdentifier:cellidentifier];
if (cell ==nil)
{
cell = [[[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier]autorelease];
}
// here set values to properties of your cell. EG set text, change color if needed, change frame if needed, etc... But not remove and add them again!
cell.usernameLable.text = [NSString stringWithFormat:#"#%#",[[homePageArray objectAtIndex:indexPath.row]objectForKey:#"sellername"]]];
//etc...
return cell;
}
I found the solution for my code
This is because of
contentview.layer.shadowOffset = CGSizeMake(0,1);
contentview.layer.shadowOpacity = 0.2;
contentview.layer.shadowRadius = 0.6;
contentview.layer.cornerRadius = 6.0; // set as
Once I remove this line from my code Its works fine
There is lot of optimalization issues in your code. You should use Instruments with Time Profiler template to detect bottlenecks.
BTW, When you draw shadow of CALayer you should set CALayer's shadowPath property for outline of the shadow. This will speed up drawing your shadow much. Please refer documentation for more details.
dialogContainer.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:dialogContainer.bounds cornerRadius:dialogContainer.layer.cornerRadius].CGPath;

Resources