I need help in iphone memory management - iphone

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.

Related

Add button to UITableViewCell

I want to add a button in a UITableViewCell. This is my code: `
if (indexPath.row==2) {
UIButton *scanQRCodeButton = [[UIButton alloc]init];
scanQRCodeButton.frame = CGRectMake(0.0f, 5.0f, 320.0f, 44.0f);
scanQRCodeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
scanQRCodeButton.backgroundColor = [UIColor redColor];
[scanQRCodeButton setTitle:#"Hello" forState:UIControlStateNormal];
[cell addSubview:scanQRCodeButton];
}`
Now, when I run the app, I see only a blank row ! Any ideas ?
While it's natural to put it in the contentView of the cell, I'm fairly certain that is not the problem (actually, in the past, I've never had subviews displayed correctly in the contentView, so I've always used the cell).
Anyway, the problem involves the first three lines of when you start creating your button. The first two lines are fine, but the code stops working with:
scanQRCodeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
buttonWithType: is actually a convenience method to create a button (it's like a compact alloc-init). Therefore, it actually "nullifies" your past two lines (you basically created the button twice). You can only use either init or buttonWithType: for the same button, but not both.
UIButton *scanQRCodeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
scanQRCodeButton.frame = CGRectMake(0.0f, 5.0f, 320.0f, 44.0f);
scanQRCodeButton.backgroundColor = [UIColor redColor];
[scanQRCodeButton setTitle:#"Hello" forState:UIControlStateNormal];
[cell addSubview:scanQRCodeButton];
This will work (note that you can use cell.contentView if you wanted). In case you're not using Automatic Reference Counting (ARC), I would like to mention that you don't have to do anything in term of memory management, because buttonWithType: returns an autoreleased button.
UIButton *deletebtn=[[UIButton alloc]init];
deletebtn.frame=CGRectMake(50, 10, 20, 20);
deletebtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[deletebtn setImage:[UIImage imageNamed:#"log_delete_touch.png"] forState:UIControlStateNormal];
[deletebtn addTarget:self action:#selector(DeleteRow:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:deletebtn];
or
// Download class and import in your project UIButton+EventBlocks
UIButton *deletebtn=[UIButton buttonWithType:UIButtonTypeRoundedRect];
[deletebtn setFrame:CGRectMake(170,5, 25, 25)];
deletebtn.tag=indexPath.row;
[deletebtn setImage:[UIImage imageNamed:#"log_delete_touch.png"] forState:UIControlStateNormal];
[deletebtn setOnTouchUpInside:^(id sender, UIEvent *event) {
//Your action here
}];
[cell addSubview:deletebtn];
You want to add any custom UI elements to the cell's contentView.
So, instead of [cell addSubview:scanQRCodeButton];
do [cell.contentView addSubview:scanQRCodeButton];
Try adding [cell.contentView addSubview:scanQRCodeButton]; or if you want the button to the left side look at my question at the answer, to move the textLabel to the side. If you want the button to the right then just set it as your accesoryView like this cell.accesoryView = scanQRCodeButton;.
Method setTitle does not work in my code, so I have set by using
[UIButton.titleLabel setText:#""]
instead of using setTitle method.
Please try again with following code:
[scanQRCodeButton.titleLabel setText:#"Hello"];
Then it would work well.

Something wrong with iphone coded button

well, i'm making an app from a UiWebView example i found. and i needed to add a button but the way this example works is similar to phonegap so i figured out i need to add the button as a subview to the window, so then i got my button and set it up for pressing but when ever i press it my app crashes... can any one help? here is my code snippet:
- (void)webViewDidFinishLoad:(UIWebView *)webView{
myLoadingLabel.hidden = YES;
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[window addSubview:webView];
//my button
UIButton *playButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
playButton.frame = CGRectMake(122, 394, 76, 76);
[playButton setTitle:#"Play" forState:UIControlStateNormal];
playButton.backgroundColor = [UIColor clearColor];
[playButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
UIImage *buttonImageNormal = [UIImage imageNamed:#"mic.png"];
UIImage *strechableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[playButton setBackgroundImage:strechableButtonImageNormal forState:UIControlStateNormal];
UIImage *buttonImagePressed = [UIImage imageNamed:#"mic.png"];
UIImage *strechableButtonImagePressed = [buttonImagePressed stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[playButton setBackgroundImage:strechableButtonImagePressed forState:UIControlStateHighlighted];
[playButton addTarget:self action:#selector(playAction:) forControlEvents:UIControlEventTouchUpInside];
[window addSubview:playButton];
}
-(void)playAction {
NSLog(#"Button Pressed!");
}
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIWebView_ExampleAppDelegate playAction:]:
oh and i know its a long shot, but i need this button outside of the webpage because it needs to start recording audio when clicked, then when clicked again it needs to stop recording and save, run a command with system();, and then put the data gotten from the system command into the uiwebview to be used... so yea if anyone knows some code i would appreciate it greatly, and its a jailbreak app so the system command will be ok. Thanks!!!
You are invoking a method named playAction: but you implement a method named playAction. Mind the missing colon. The crash most likely is related to that issue.
For a quick fix, change
[playButton addTarget:self action:#selector(playAction:) forControlEvents:UIControlEventTouchUpInside];
to
[playButton addTarget:self action:#selector(playAction) forControlEvents:UIControlEventTouchUpInside];
The problem is this:
#selector(playAction:)
vs.
- (void)playAction
The former refers to a method called -playAction: that takes one parameter, but you’ve implemented a method called -playAction that takes no parameters. Drop the colon from the #selector block and it should work.

Loading Multiple Images from Server on UIButtons??

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.

Create toolbar for quiz app

This is related to a question i posted earlier.I am still stuck on it.Heres a description.I am creating a quiz app.It has a toolbar whose buttons are to be created dynamicaly each time the user clicks a button.I did it using a method which adds three buttons into an arrray, then uses a for loop to check the number of choices the question has and then create and add a button to the array for each choice.Later i use
[toolbar setitems:tempArray];
to add the buttons
But while doing this i am running into memory leaks.The app crashes after 200 questions.I found using instruments that the leaks were in button creation area.But after doing many experiments im at a loss about what to do.
I also have another question
Is there a way to find out the retain count of objects created by built in methods in iphone sdk.Specificaly,
1)Does NSMutableArray's addobject method increase the retain count of the added object
2)Is [[toolbar items] release] likely to cause trouble if i am intending to release the customBarButtonItem objects stored in it?
because wile playing with these options , the app either crashes immediately or the changes have no effect on the reported leaks
heres the code.Its got a lot of comment lines which are options i tried
- (void)CreateButtons{
UIToolbar *tempToolBar=[[UIToolbar alloc] ]
numberOfChoices=0;//set number of choice buttons at present to 0
NSMutableArray *tempItems=[[NSMutableArray alloc] init];//Array for holding the buttons
Question *question=[currentQuestion question];
NSString *answer=[question answerOptions];
int numericAnswer=0;
numericAnswer=[answer characterAtIndex:0];
//see if its a number or a character
if (numericAnswer > 96) { // its a character
int choice;
for (choice=97; choice <=numericAnswer ; choice ++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:#"gembtnblu.png"] forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH , TOOLBAR_BUTTON_HEIGHT);
[button setTitle:[NSString stringWithFormat:#"%c",(char)choice] forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button addTarget:self action:#selector(ChoiceButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:choice];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
if (isReviewing == TRUE) {
customBarItem.customView.userInteractionEnabled=FALSE;
}
//Add button to the array
[tempItems addObject:customBarItem];
//release buttons
[customBarItem release];
numberOfChoices++;
}
}
else {
int choice;
for (choice=49; choice<=numericAnswer; choice ++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:#"gembtnblu.png"] forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH , TOOLBAR_BUTTON_HEIGHT);
[button setTitle:[NSString stringWithFormat:#"%c",choice] forState:UIControlStateNormal];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button addTarget:self action:#selector(ChoiceButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
[button setTag:choice];
UIBarButtonItem *customBarItem = [[UIBarButtonItem alloc] initWithCustomView:button];
//Add button to the array
[tempItems addObject:customBarItem];
if (isReviewing == TRUE) {
customBarItem.customView.userInteractionEnabled=FALSE;
}
//release buttons
[customBarItem release];
numberOfChoices++;
}
}
//load the image
UIButton *previousButton = [UIButton buttonWithType:UIButtonTypeCustom];
[previousButton setBackgroundImage:[UIImage imageNamed:#"prev.png"] forState:UIControlStateNormal];
[previousButton addTarget:self action:#selector(PreviousClicked:) forControlEvents:UIControlEventTouchUpInside];
previousButton.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH , TOOLBAR_BUTTON_HEIGHT);
UIBarButtonItem *customBarItem6 = [[UIBarButtonItem alloc] initWithCustomView:previousButton];
//[previousButton release];
self.prevButton=customBarItem6;
UIButton *nextButton= [UIButton buttonWithType:UIButtonTypeCustom];
[nextButton setBackgroundImage:[UIImage imageNamed:#"nex.png"] forState:UIControlStateNormal];
[nextButton addTarget:self action:#selector(nextClicked:) forControlEvents:UIControlEventTouchUpInside];
nextButton.frame = CGRectMake(0, 0, TOOLBAR_BUTTON_WIDTH, TOOLBAR_BUTTON_HEIGHT);
UIBarButtonItem *customBarItem7 = [[UIBarButtonItem alloc] initWithCustomView:nextButton];
//[nextButton release];
//Use this to put space in between your toolbox buttons
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[tempItems addObject:flexItem];
[tempItems addObject:customBarItem6];
[tempItems addObject:customBarItem7];
//release buttons
[customBarItem6 release];
[customBarItem7 release];
[flexItem release];
//NSArray *items=[[NSArray alloc] initWithArray:(NSArray *)tempItems];
//[tempItems release];
//add array of buttons to toolbar
//if([[toolbar items] count]>0)
// {
// [[toolbar items] release];
// }
[toolbar setItems:tempItems animated:YES];
//[items release];
//[self.view addSubview:toolbar];
if(isReviewing == FALSE && isPractice == FALSE) {
prevButton.enabled=FALSE;
}
//[toolbar bringSubviewToFront:customBarItem6.customView];
}
toolbar is created via ib
Yeah its a lot of code but it just creates buttons based on number of choices for a question.The two for loops are similar exept one puts a,b,c,d on the buttons while the other one puts 1,2,3,4.....In addition three buttons are created.One for next, previous and a flex item .This method is is called each time the user clicks teh next button.
I can see a few things which are not very efficient memory-wise:
You use lots of convenience initializers: buttonWithType and 'imageNamed`. These will autorelease themselves at some point in the future but not within your method.
The item tempToolbar is allocated but never released. This will leak.
Your mutable array tempItems also does not appear to be released: this will kill you completely since all your buttons are added to it...
Based on this I would suggest:
Use of alloc/init methods instead of convenience constructors
Alternatively: create an NSAutoReleasePool at the start of your method and drain it at the end: this will release all autoreleased entities.
Good luck
Difficult to follow all that code, but an easy part-answer to 1) is that, yes, [NSMutableArray addObject:] increase retain +1.

Do we need to release an UIImage object even not allocated memory?

I added an image to button
UIImage* deleteImage = [UIImage imageNamed:#"Delete.png"];
CGRect imageFrame=CGRectMake(-4,-4, 310, 55);
[btn setFrame:imageFrame];
btn.backgroundColor=[UIColor clearColor];
[btn setBackgroundImage:deleteImage forState:UIControlStateNormal];
[btn setTitle:#"Delete" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(editDeleteAction) forControlEvents:UIControlEventTouchUpInside];
[elementView addSubview:btn];
[deleteImage release];// do we need to release the image here
If I release here its working fine but in object allocations no.of image count is increasing.
If you create an image with the imageNamed: message you don't have to release it, because you get an autoreleased image back.
Only if you create the image with one of the init...: messages you have to release it later on.
"imageNamed:" method gives an autoreleased object, so you don't have to release object.
FYI: "imageNamed:" method uses an internal cache (you may face memory warning if imageNamed: method used extensively). It is better to remove cache on receiving warnings.
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
[[ImageCache sharedImageCache] removeAllImagesInMemory];
}
Go through this guide http://akosma.com/2009/01/28/10-iphone-memory-management-tips/