Loading Multiple Images from Server on UIButtons?? - iphone

i am trying to upload 8-10 thumbnail images on UIButton. The images are loaded directly via Links to my server for eg. www.abc.com/fire.png. I have placed these UIButtons inisde a Scrollview. the following code is how i achieve it. but whenever this method gets called my applications hangs up as i guess the images take time to load on the buttons. How can i stop my app from getting stuck for few seconds??
- (void)loadSCRView
{
[self.view addSubview:scrollView];
for (i = 0; i < [myEngine.logoUrlArr count]; i++)
{
NSString *imageName = [NSString stringWithFormat:#"%#",[myEngine.logoUrlArr objectAtIndex:i]];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL: [NSURL URLWithString:imageName] options:NSDataReadingUncached error:nil]];
UIButton *btn = [[UIButton alloc]init];
[btn setImage:image forState:UIControlStateNormal];
[btn setFrame:CGRectMake(x, 4, 57, 57)];
x=x+ 70.00;
btn.tag = i;
[scrollView addSubview:btn];
[btn addTarget:self action:#selector(click:) forControlEvents:UIControlEventTouchDown];
UILabel *label = [[UILabel alloc]init];
label.text = [myEngine.nameArr objectAtIndex:i];
[label setFont:[UIFont fontWithName:#"Helvetica" size:12]];
[label setTextColor:[UIColor whiteColor]];
[label setBackgroundColor:[UIColor clearColor]];
[label setFrame:CGRectMake(btn.frame.origin.x , 59, 70, 20)];
//[label setFrame:CGRectMake(100 , 59, 70, 20)];
y=y+ 100.00;
[scrollView addSubview:label];
[btn release];
[label release];
}

You should try to fetch these images (preferably in a background thread) before the scroll view is displayed. Save these on the disk & use them in the scroll view. A network operation will generally not be that fast that you don't observe a lag.
HTH,
Akshay

To avoid freezing you have to go with NSOperationQueue. Here is a good and appropriate example...

You can use threads so that download the image in the background thread & cache it.So that next time your performance will be good.

Related

Place custom view on Navigation Bar

I want to display Image,Title name,and two left right buttons. That I have done successfully.
Here is the code:
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 200, 100)];
UIButton *leftButton = [[UIButton alloc]init];
[leftButton setImage:[UIImage imageNamed:#"previous-arrow.png"] forState:UIControlStateNormal];
[leftButton addTarget:self action:#selector(goPrevious:) forControlEvents:UIControlEventTouchUpInside];
[leftButton setFrame:CGRectMake(20, 50, 14, 13)];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Title.png"]];
[imageView setFrame:CGRectMake(leftButton.frame.origin.x+leftButton.frame.size.width+4, 20, 50, 50)];
UILabel *nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(imageView.frame.origin.x+imageView.frame.size.width+4, 30, 100, 40)];
NSString *cName = [NSString stringWithFormat:#"%#",[NameArray objectAtIndex:indexPath.section]];
[nameLabel setTextColor:[UIColor whiteColor]];
[nameLabel setBackgroundColor:[UIColor clearColor]];
[nameLabel setContentMode:UIViewContentModeScaleAspectFill];
[nameLabel setTextAlignment:UITextAlignmentLeft];
CGSize expectedLabelSize = [cName sizeWithFont:nameLabel.font
constrainedToSize:CGSizeMake(100, 40)
lineBreakMode:nameLabel.lineBreakMode];
[nameLabel setFrame:CGRectMake(imageView.frame.origin.x+imageView.frame.size.width+4, 35, expectedLabelSize.width, expectedLabelSize.height)];
nameLabel.text=cName;
UIButton *rightButton = [[UIButton alloc]init];
[rightButton setImage:[UIImage imageNamed:#"next-arrow.png"] forState:UIControlStateNormal];
[rightButton setFrame:CGRectMake(nameLabel.frame.origin.x+nameLabel.frame.size.width+4, 50, 14, 13)];
[rightButton addTarget:self action:#selector(next:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:nameLabel];
[view addSubview:imageView];
[view addSubview:leftButton];
[view addSubview:rightButton];
self.navigationItem.titleView = view;
This code is written in cellForRowAtIndexPath. The view is showing properly on navigation bar but after scrolling the tableview. Initially it is displaying on wrong coordinates.
Please Suggest.
Put this code in viewWillAppear or viewDidAppear. It's not meant to be in tableView protocol!

objective c addSubview order

i am a junior programmer
I face a problem of some of the subview in the program not shown ,
don't know if it is the addsubview order problem or the others .
hope if anyone can provide a suggestion or solution .thanks all
for (int i = 0; i < NUM_DISHES; i++) {
UIImageView* img_steps = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"%d.jpg", i]]];
//IMPORTANT: The i*W_IPAD means that 1st 0*1024 , 1*1024 , 2*1024.............and so on
[img_steps setFrame:CGRectMake(W_IPAD, 0, W_IPAD , H_UPFR)];
UIImageView* imageset = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[ary_img objectAtIndex:i]]];
[imageset setFrame:CGRectMake(89, 9, H_INGREPHOTO, W_INGREPHOTO)];
[ary_image addObject:imageset];
//ingredient amount section
UILabel* lbl_amt = [[UILabel alloc] initWithFrame:CGRectMake(128, 177, 190, 33)];
[lbl_amt setText:[ary_amount objectAtIndex:i]];
[lbl_amt setFont:[UIFont systemFontOfSize:25]];
[lbl_amt setTextColor:[UIColor blackColor]];
[lbl_amt setBackgroundColor:[UIColor clearColor]];
[ary_amt addObject:lbl_amt];
//method section
UILabel* lbl_method = [[UILabel alloc] initWithFrame:CGRectMake(596, 93, 130, 32)];
[lbl_method setText:[ary_meth objectAtIndex:i]];
[lbl_method setBackgroundColor:[UIColor clearColor]];
[lbl_method setFont:[UIFont systemFontOfSize:30]];
[lbl_method setTextColor:[UIColor blackColor]];
[ary_method addObject:lbl_method];
//alpha bar step number step number section
UILabel* lbl_numberstep = [[UILabel alloc] initWithFrame:CGRectMake(90 + (130 * i), 5, W_NUMBERSTEP, H_NUMBERSTEP)];
[lbl_numberstep setText:[NSString stringWithFormat:#"%d",i + 1]];
[lbl_numberstep setFont:[UIFont systemFontOfSize:20]];
[lbl_numberstep setBackgroundColor:[UIColor clearColor]];
[lbl_numberstep setTextColor:[UIColor blackColor]];
[self.view addSubview:img_steps];
[alpha_bar addSubview:lbl_numberstep];
[alphaframe addSubview:[ary_method objectAtIndex:i]];
[alphaframe addSubview:[ary_amt objectAtIndex:i]];
[alphaframe addSubview:[ary_image objectAtIndex:i]];
}
// Section --- Add Subview
[self.view addSubview:background];
[background addSubview:main_view];
[main_view addSubview:alpha_bar];
[main_view addSubview:alphaframe];
[main_view addSubview:but_transit_to_a]; //can add to the main_view
[main_view addSubview:left_buttom];
[main_view addSubview:right_buttom];
[alpha_bar addSubview:bar];
[alpha_bar addSubview:lbl_lastnum];
[alphaframe addSubview:but_transit_to_c];
}
return self;
}
To bring the subview to front you can use [yourMainView bringSubviewToFront:yoursubview]. If your subview isn't showing then, check that you've properly set up the subview's frame and that hidden = NO.
The view.subviews array holds the bottom-most view in index zero, and holds views in an order relating to their "z-index". So [myView.subviews lastObject]; will always give the view in front of all other views and [myView.subviews objectAtIndex:0]; will have the view below all views in that array.
From the UIView docs - subviews property:
You can use this property to retrieve the subviews associated with
your custom view hierarchies. The order of the subviews in the array
reflects their visible order on the screen, with the view at index 0
being the backmost view. For complex views declared in UIKit and other
system frameworks, any subviews of the view are generally considered
private and subject to change at any time. Therefore, you should not
attempt to retrieve or modify subviews for these types of
system-supplied views. If you do, your code may break during a future
system update.

I need help in iphone memory management

I am developing application which is using many photos so definitely it crashes though i released the images as some part is shown in following code
-(void)addScrollView{
[self selectData];
scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(5, 0, 300, 160)];
int counter=10;
float y=10.0f;
int fullLength=[photoArray count];
int horizontal=(fullLength/2)*80;
int vertical=160;
int c1=1;
for(int c=0;c<[photoArray count];c++){
PhotoData *d=[photoArray objectAtIndex:c];
//NSLog(d.photoPath);
if(c==fullLength/2 &&c1<3){
counter=10;
y=y+80.0f;
c1++;
}
UIImage *img1=[[UIImage alloc]initWithContentsOfFile:d.photoPath];
UIButton* button = [[UIButton alloc] init];
[button setTitle:#"Delete" forState:UIControlStateNormal];
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
button.tag=d.photoId;
//set the button states you want the image to show up for
[button setBackgroundImage:img1 forState:UIControlStateNormal];
[button setFrame:CGRectMake(counter, y, 70.0, 70.0)];
//create the touch event target, i am calling the 'productImagePressed' method
[button addTarget:self action:#selector(deleteImage:)
forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:button];
counter=counter+80.0f;
[img1 release];
[button release];
}
[scrollView setContentSize:CGSizeMake(horizontal, vertical)];
[self.view addSubview:scrollView];
[scrollView release];
}
Dealloc is also not called because i am using tabbased application.
So please help how can solve this memory management issue.
The only issue is what you mentioned—that you might have too many images or objects loaded. In that case, you may want to save some data to a file behind the scenes, and do fetches as needed. Maybe instead of storing all the objects in photoArray, write to a file (you could even just write the file path to a file) and batch load ten or so at a time, rather than all of them. Without more info though, there's not much more I can say.

UIView or UIScrollView doesn't refresh the display on programmatically created controls

I'm creating melodramatically some controls, and they don't appear, it needs some kind of a refresh method..
here's my layout:
it's a chat, and all those messages I'm creating them dynamically as the event appears,
what I'm creating at startup, it does appear, but what I'm creating afterward fails to show, even if the code is ok,
here's how am I creating the controls (by calling the following function):
- (void) AddNewMessage: (NSString *)msg date1:(NSString* ) date2 {
NSString *backimage =[NSString stringWithString:#""];
NSString *who =[NSString stringWithString:#"1"];
calculatedHeight=floor( msg.length / 40 )*20;
if (calculatedHeight<30) calculatedHeight=30;
if ([who isEqualToString:#"1"]) {
left=85;
left_hour_button=25;
backimage=#"green_bubble.png";
}
else {
left=5;
left_hour_button=240;
backimage=#"grey_bubble.png";
}
UIButton *button1 = [[UIButton alloc] initWithFrame:CGRectMake(left, lastcalculatedHeight-10, 230, calculatedHeight+10)];
[button1 setBackgroundImage:[[UIImage imageNamed:backimage] stretchableImageWithLeftCapWidth:9 topCapHeight:13] forState:UIControlStateDisabled];
[button1 setEnabled:FALSE];
[scrollView addSubview:button1];
[button1 release];
UIButton *buttonTime = [[UIButton alloc] initWithFrame:CGRectMake(left, lastcalculatedHeight+40, 50, 20)];
[buttonTime setBackgroundImage:[[UIImage imageNamed:#"hour_bubble.png"] stretchableImageWithLeftCapWidth:9 topCapHeight:13] forState:UIControlStateDisabled];
[buttonTime setFrame:CGRectMake(left_hour_button, lastcalculatedHeight+calculatedHeight-30, 55, 25)];
[buttonTime setTitle:date2 forState:UIControlStateDisabled];
[buttonTime setTitleColor:[UIColor blackColor] forState:UIControlStateDisabled];
buttonTime.titleLabel.font=[UIFont fontWithName:#"Helvetica" size:8.0];
buttonTime.titleLabel.lineBreakMode= UILineBreakModeWordWrap;
[buttonTime setEnabled:FALSE];
[scrollView addSubview:buttonTime];
[buttonTime release];
UILabel *labelMessage = [[UILabel alloc] initWithFrame:CGRectMake(left+5, lastcalculatedHeight-5, 220, calculatedHeight)];
[labelMessage setText:msg];
[labelMessage setFont:[UIFont fontWithName:#"Arial" size:12.0]];
[labelMessage setLineBreakMode:UILineBreakModeWordWrap];
[labelMessage setTextColor:[UIColor blackColor]];
[labelMessage setAdjustsFontSizeToFitWidth:NO];
[labelMessage setNumberOfLines:floor( msg.length / 40 )+2];
[labelMessage setBackgroundColor:[UIColor clearColor]];
[scrollView addSubview:labelMessage];
[labelMessage release];
lastcalculatedHeight+=calculatedHeight+20;
totalHeight+=calculatedHeight;
scrollView.contentSize = CGSizeMake(240, lastcalculatedHeight);
}
How do I "refresh" the display?
The scrollView is an object inside the Uiview from which the class derives
Also I will want to scroll down to the bottom the scrollview, each time I'm adding a new message.
I've seen this post but either it doesn't work, or it acts weird on the simulator...
haven't tried it on a device because I don't own an iPhone yet.
it scrolls too much or at all, but if I go to another tab, then switch back, the scroll is scrolled at the bottom, and it even shows the controls I've created programmatically...
Weird isn't it?
Try using [self.view setNeedsDisplay], if self is a view controller, or just [scrollView setNeedsDisplay].

tableview cell load all at once in iphone

I have implemented following code in my application.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = [NSString stringWithFormat:#"%#%i",searchQueryString,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
XML_SearchResult *t=[arrayResults objectAtIndex:indexPath.row];
cell=((indexPath.row%2)==0) ?
[self getCellContentView:CellIdentifier drillTitle:t.drill_title stroke_type:t.stroke_type exercise_type:t.exercise_type level_name:t.level_name age_range:t.age_range alterNate:NO] :
[self getCellContentView:CellIdentifier drillTitle:t.drill_title stroke_type:t.stroke_type exercise_type:t.exercise_type level_name:t.level_name age_range:t.age_range alterNate:YES] ;
CGRect a=[cell frame];
UIImageView *bImg=[[UIImageView alloc] initWithFrame:a];
bImg.image=[UIImage imageNamed:#"white-rect-tab-3.png"];
[bImg setContentMode:UIViewContentModeScaleToFill];
cell.selectedBackgroundView=bImg; [bImg release];
}
return cell;
}
-(UITableViewCell*)getCellContentView:(NSString*)cellIdentifier drillTitle:(NSString*)drillTitle stroke_type:(NSString*)stroke_type exercise_type:(NSString*)exercise_type level_name:(NSString*)level_name age_range:(NSString*)age_range alterNate:(BOOL)alterNate
{
CGRect label1Frame=CGRectMake(5, 20, 260, 32),label2Frame=CGRectMake(5, 62, 120, 30),label3Frame=CGRectMake(130, 62, 170, 30);//,BgFrame=CGRectMake(0, 0, 320, 60);
UITableViewCell *cell=[[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 312, 95) reuseIdentifier:cellIdentifier] autorelease];
UILabel *tmp; UIImageView *imgBg;
cell.backgroundColor=[UIColor clearColor];
// drill title label
tmp=[[UILabel alloc] initWithFrame:CGRectMake(5, 1, 260, 32)];
tmp.textColor=[UIColor colorWithRed:(9.0/255.0) green:(68.0/255) blue:(85.0/255) alpha:1.0];
[tmp setFont:[UIFont fontWithName:#"ArialRoundedMTBold" size:18]]; tmp.text=drillTitle; [tmp setShadowColor:[UIColor lightGrayColor]];
tmp.backgroundColor=[UIColor clearColor]; [cell.contentView addSubview:tmp]; [tmp release];
// title label - tip
tmp=[[UILabel alloc] initWithFrame:label1Frame];
tmp.textColor=[UIColor colorWithRed:(9.0/255.0) green:(68.0/255) blue:(85.0/255) alpha:1.0];
[tmp setFont:[UIFont fontWithName:#"ArialRoundedMTBold" size:18]]; tmp.text=stroke_type; [tmp setShadowColor:[UIColor lightGrayColor]];
tmp.backgroundColor=[UIColor clearColor]; [cell.contentView addSubview:tmp]; [tmp release];
// sub title - exercise type label - tip
tmp=[[UILabel alloc] initWithFrame:CGRectMake(5, 40 , 260, 32)];
tmp.textColor=[UIColor colorWithRed:(14.0/255.0) green:(105.0/255) blue:(128.0/255) alpha:1.0];
[tmp setFont:[UIFont fontWithName:#"ArialRoundedMTBold" size:15]]; tmp.text=exercise_type; [tmp setShadowColor:[UIColor lightGrayColor]];
tmp.backgroundColor=[UIColor clearColor]; [cell.contentView addSubview:tmp]; [tmp release];
// Age - Range
tmp=[[UILabel alloc] initWithFrame:label2Frame]; tmp.adjustsFontSizeToFitWidth=0; tmp.text=[NSString stringWithFormat:#"Age Range : %#",age_range];
tmp.textColor= [UIColor blackColor];//[UIColor colorWithRed:(14.0/255.0) green:(105.0/255) blue:(128.0/255) alpha:1.0];// : [UIColor blackColor] ;
[tmp setBackgroundColor:[UIColor clearColor]];
[tmp setFont:[UIFont fontWithName:#"ArialMT" size:14]]; [tmp setShadowOffset:CGSizeMake(1,1)]; [tmp setShadowColor:[UIColor lightGrayColor]];
[cell.contentView addSubview:tmp]; [tmp release];
// Difficulty leve - Range
tmp=[[UILabel alloc] initWithFrame:label3Frame]; tmp.adjustsFontSizeToFitWidth=0; tmp.text=[NSString stringWithFormat:#"| Diff. Level : %#",level_name];
tmp.textColor=[UIColor blackColor];//[UIColor colorWithRed:(14.0/255.0) green:(105.0/255) blue:(128.0/255) alpha:1.0];
[tmp setShadowColor:[UIColor lightGrayColor]];
[tmp setBackgroundColor:[UIColor clearColor]];
[tmp setFont:[UIFont fontWithName:#"ArialMT" size:14]]; [tmp setShadowOffset:CGSizeMake(1,1)];
[cell.contentView addSubview:tmp]; [tmp release];
// arrow
imgBg=[[UIImageView alloc] initWithFrame:CGRectMake(280, 35, 13, 13)]; imgBg.contentMode=UIViewContentModeScaleToFill;
imgBg.image=[UIImage imageNamed:#"arrow-2.png"];
[cell.contentView addSubview:imgBg]; [cell.contentView sendSubviewToBack:imgBg]; [imgBg release];
// line
imgBg=[[UIImageView alloc] initWithFrame:CGRectMake(-4, 94, 298, 2)]; imgBg.contentMode=UIViewContentModeScaleToFill;
imgBg.image=[UIImage imageNamed:#"line.png"];
[cell.contentView addSubview:imgBg]; [cell.contentView sendSubviewToBack:imgBg]; [imgBg release];
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
return cell;
}
That's all about customizing cell dynamically.
But the problem is - first time only visible cells are created, then after - user tries to scroll down. other cells which are going to be visible is going to be created & then displayed. Due to this, there is some delay in scrolling tableview at first time.
What is the solution for this ?
When developing for mobile platforms, you need to be concerned about memory footprints. I feel that if you tried to load 400 cells with images all at once, you might be asking for trouble. It's not the recommended method and you will certainly introduce a huge delay in loading this.
Instead of hacking like this, work in improving the performance of your cellForIndexPath function to make it load quicker. Or asynchronously.
It is probably the image loading which takes all the time. Creating cells should not take very long, especially if you reuse old ones.
If the images are often the same, then you could cache those. Also scaling takes time and also if the images are not PNG they will take longer to load.
But the solution for me has been to not load the images when I create the cell, i.e. NOT in:
tableView:cellForRowAtIndexPath:
but instead implement:
scrollViewDidEndDecelerating
This is a delegate function which is called when the table stops scrolling. Then you can get a list of the visible cells (indexPathsForVisibleRows) and set the image on each of those.