I load a UITableView with data, see code below, and all works well initially. However, when i scroll the table view it crashes. I cannot find where the dealloc problem is and wonder if someone nice and experienced could give me a hint?
I have updated this post with the full code including the loading of the array.
The 'retain'(s) was put there for testing.
When i take a way the cellValue1 i do not have the problem but then i do not have any data to display.
I get the following message:
[CFString isEqualToString:]: message sent to deallocated instance 0x5e5ae70
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Topplista";
AccessPlayerData *readPlayerDataFunction = [AccessPlayerData new];
NSMutableArray *leaderboardArray = [[NSMutableArray alloc] initWithCapacity:0];
leaderboardArray = [readPlayerDataFunction readPlayersFileForLeaderBoard];
cellArray1 = [[NSMutableArray alloc]init];
cellArray2 = [[NSMutableArray alloc]init];
NSString *keyName = [[NSString alloc]init]; // Player name
double percentCorrectAnswers = 0; // % correct answers
double nrCorrectAnswers = 0; // # correct answers
double totalNrQuestions = 0; // # questions ever answered
nrOfPlayers = [leaderboardArray count] / 3;
keyName = [leaderboardArray objectAtIndex:3];
nrCorrectAnswers = [[leaderboardArray objectAtIndex:4]doubleValue];
totalNrQuestions = [[leaderboardArray objectAtIndex:5]doubleValue];
percentCorrectAnswers = (nrCorrectAnswers / totalNrQuestions) * 100;
int loop = 0;
int loop2 = 2;
int counter = 1;
for (int oo = 0; oo < nrOfPlayers; oo++) {
if ([[leaderboardArray objectAtIndex:loop2]intValue] > 0) {
keyName = [leaderboardArray objectAtIndex:loop];
loop++;
nrCorrectAnswers = [[leaderboardArray objectAtIndex:loop]doubleValue];
loop++;
totalNrQuestions = [[leaderboardArray objectAtIndex:loop]doubleValue];
loop++;
percentCorrectAnswers = (nrCorrectAnswers / totalNrQuestions) * 100;
[cellArray1 addObject:keyName]; // Player name
[cellArray1 addObject:[NSNumber numberWithDouble:totalNrQuestions]];
[cellArray1 addObject:[NSNumber numberWithDouble:nrCorrectAnswers]];
[cellArray1 addObject:[NSNumber numberWithDouble:percentCorrectAnswers]];
counter++;
}
else {
loop = loop + 3;
}
loop2 = loop2 + 3;
}
self.sortArray;
rowCount = [cellArray1 count];
[keyName retain];
[readPlayerDataFunction release];
[keyName release];
[leaderboardArray release];
}
- (void)sortArray {
//outputArray
NSMutableArray *dummyArray = [[NSMutableArray alloc]initWithCapacity:0];
NSMutableArray *editPlayerArray = [[NSMutableArray alloc] initWithArray:cellArray1];
NSArray *sortedArray = [[NSArray alloc]init];
int nrOfActivePlayers = [cellArray1 count] / 4;
int counteR = 2;
for (int qq = 0; qq < nrOfActivePlayers; qq++) {
[dummyArray addObject:[cellArray1 objectAtIndex:counteR]];
counteR = counteR + 4;
}
// Sort the array
sortedArray = [dummyArray sortedArrayUsingSelector:#selector(compare:)];
int rank = 0;
int roller = [editPlayerArray count] / 4;
int oldNrAnswers = 0;
NSMutableArray *finalArray = [[NSMutableArray alloc]initWithCapacity:0];
for (int qq = nrOfActivePlayers - 1; qq > -1; qq--) {
counteR = 2;
for (int rr = 0; rr < roller; rr++) {
if ([[editPlayerArray objectAtIndex:counteR]intValue] == [[sortedArray objectAtIndex:qq]intValue]) {
//=====FIX RANKING IF THERE IS MORE THAN ONE PLAYER WITH THE SAME RESULT=====//
if ([[editPlayerArray objectAtIndex:counteR]intValue] == oldNrAnswers) {
if (rank == 0) rank = 1;
}
else {
rank++;
}
[finalArray addObject:[NSNumber numberWithInt:rank]]; // Rank
[finalArray addObject:[editPlayerArray objectAtIndex:counteR - 2]]; // Player name
[finalArray addObject:[editPlayerArray objectAtIndex:counteR - 1]]; // Asked questions
[finalArray addObject:[editPlayerArray objectAtIndex:counteR]]; // Correct answers
oldNrAnswers = [[editPlayerArray objectAtIndex:counteR]intValue];
[finalArray addObject:[editPlayerArray objectAtIndex:counteR + 1]]; // % correct answers
[editPlayerArray removeObjectAtIndex:counteR - 2];
[editPlayerArray removeObjectAtIndex:counteR - 2];
[editPlayerArray removeObjectAtIndex:counteR - 2];
[editPlayerArray removeObjectAtIndex:counteR - 2];
roller = [editPlayerArray count] / 4;
break;
}
else {
counteR = counteR + 4;
}
}
}
[sortedArray retain];
[cellArray1 removeAllObjects];
nrOfPlayers = [finalArray count] / 5;
counteR = 0;
NSString *cellValue1 = [[NSString alloc]init];
NSString *cellValue2 = [[NSString alloc]init];
//======FORMAT THE ARRAY INTO TWO ARRAYS FOR DEPLOYMENT=======//
for (int qq = 0; qq < nrOfPlayers; qq++) {
cellValue1 = [NSString stringWithFormat:#"%i. %# (Antal rätt svar: %.0f)",
[[finalArray objectAtIndex:counteR]intValue],
[finalArray objectAtIndex:counteR + 1],
[[finalArray objectAtIndex:counteR + 3]doubleValue]];
cellValue2 = [NSString stringWithFormat:#"Antal frågor: %.0f : Procent rätt svar: %.1f%%",
[[finalArray objectAtIndex:counteR + 2]doubleValue],
[[finalArray objectAtIndex:counteR + 4]doubleValue]];
counteR = counteR + 5;
[cellArray1 addObject:cellValue1];
[cellArray2 addObject:cellValue2];
}
[dummyArray release];
[editPlayerArray release];
[sortedArray release];
[finalArray release];
[cellValue1 release];
[cellValue2 release];
}
- (UITableViewCell *) getCellContentView:(NSString *)cellIdentifier {
CGRect CellFrame = CGRectMake(0, 0, 300, 60);
CGRect Label1Frame = CGRectMake(10, 10, 290, 25);
CGRect Label2Frame = CGRectMake(30, 33, 270, 25);
UILabel *lblTemp;
UITableViewCell *cell = [[[UITableViewCell alloc] initWithFrame:CellFrame reuseIdentifier:cellIdentifier] autorelease];
//Initialize Label with tag 1.
lblTemp = [[UILabel alloc] initWithFrame:Label1Frame];
lblTemp.backgroundColor = [UIColor orangeColor];
[lblTemp setFont:[UIFont fontWithName:#"American Typewriter" size:16]];
lblTemp.tag = 1;
[cell.contentView addSubview:lblTemp];
[lblTemp release];
//Initialize Label with tag 2.
lblTemp = [[UILabel alloc] initWithFrame:Label2Frame];
lblTemp.backgroundColor = [UIColor orangeColor];
lblTemp.tag = 2;
[lblTemp setFont:[UIFont fontWithName:#"American Typewriter" size:13]];
lblTemp.textColor = [UIColor whiteColor];
[cell.contentView addSubview:lblTemp];
[lblTemp release];
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
tableView.backgroundColor = [UIColor orangeColor];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
cell = [self getCellContentView:CellIdentifier];
UILabel *lblTemp1 = (UILabel *)[cell viewWithTag:1];
UILabel *lblTemp2 = (UILabel *)[cell viewWithTag:2];
NSLog(#" ");
NSLog(#" ");
NSLog(#" ");
NSLog(#"============");
NSLog(#"cA1: %i", [cellArray1 count]);
NSLog(#"cA2: %i", [cellArray2 count]);
NSLog(#"rowCount %i", rowCount);
NSLog(#"ixP row: %i", indexPath.row);
NSString *cellValue1 = [cellArray1 objectAtIndex:indexPath.row];
// NSString *cellValue2 = [cellArray2 objectAtIndex:indexPath.row];
[cellValue1 retain]; // for testing
// [cellValue2 retain]; // for testing
NSLog(#"cV1: %#", cellValue1);
NSLog(#"cV2: %#", #"cellValue2");
lblTemp1.text = cellValue1;
lblTemp2.text = #"cellValue2";
return cell;
}
Here is the result:
2011-03-09 21:33:23.850 FamQuiz_R0_1[842:207] cV2: cellValue2
2011-03-09 21:33:23.850 FamQuiz_R0_1[842:207]
2011-03-09 21:33:23.851 FamQuiz_R0_1[842:207]
2011-03-09 21:33:23.851 FamQuiz_R0_1[842:207]
2011-03-09 21:33:23.852 FamQuiz_R0_1[842:207] ============
2011-03-09 21:33:23.852 FamQuiz_R0_1[842:207] cA1: 7
2011-03-09 21:33:23.853 FamQuiz_R0_1[842:207] cA2: 7
2011-03-09 21:33:23.853 FamQuiz_R0_1[842:207] rowCount 7
2011-03-09 21:33:23.853 FamQuiz_R0_1[842:207] ixP row: 5
2011-03-09 21:33:23.854 FamQuiz_R0_1[842:207] cV1: 5. Barnspelare (Antal rätt svar: 2)
2011-03-09 21:33:23.854 FamQuiz_R0_1[842:207] cV2: cellValue2
2011-03-09 21:33:27.370 FamQuiz_R0_1[842:207]
2011-03-09 21:33:27.371 FamQuiz_R0_1[842:207]
2011-03-09 21:33:27.371 FamQuiz_R0_1[842:207]
2011-03-09 21:33:27.372 FamQuiz_R0_1[842:207] ============
2011-03-09 21:33:27.373 FamQuiz_R0_1[842:207] cA1: 7
2011-03-09 21:33:27.373 FamQuiz_R0_1[842:207] cA2: 7
2011-03-09 21:33:27.374 FamQuiz_R0_1[842:207] rowCount 7
2011-03-09 21:33:27.374 FamQuiz_R0_1[842:207] ixP row: 6
2011-03-09 21:33:27.375 FamQuiz_R0_1[842:207] *** -[CFString retain]: message sent to deallocated instance 0x5b446a0
You shouldn't release cellValue1 releaseand cellValue2. Getting them by calling objectAtIndex: does not retain them.
Here's an idea - perhaps the error is somewhere in here.
UILabel *lblTemp1 = (UILabel *)[cell viewWithTag:1];
UILabel *lblTemp2 = (UILabel *)[cell viewWithTag:2];
NSString *cellValue1 = [cellArray1 objectAtIndex:indexPath.row];
NSString *cellValue2 = [cellArray2 objectAtIndex:indexPath.row];
lblTemp1.text = cellValue1;
lblTemp2.text = cellValue2;
Either [cellArray1 objectAtIndex:indexPath.row] or [cellArray2 objectAtIndex:indexPath.row] is null
OR
[cellArray1 objectAtIndex:indexPath.row] or [cellArray2 objectAtIndex:indexPath.row] is null.
In the first case, the program crashes when you try to assign a value to a null lblTemp1.txt.
In the second case, the program crashes because NSString* cellValue is null and it then tries to display the null string.
You should be able to use the debugger to step through and figure out the values of these things as you go, and figure where the error is happening.
Given that your program initially works then dies when you scroll, I am wondering if the cellArray1 and cellArray2 where you are drawing your values from actually have as much data as the number of lines you have asked the scrollView it to display. Maybe you have less data than the number of lines you have specified in the TableViewDatasource?
The data is being released right after the tableView has been created so when you scroll, the app crashes. Try to post all of the codes in .m file for the people to see the problem. I am sure it's not in the codes you posted.
How do you add the data in cellArray1 and cellArray2. Can you please post the code where you populate these arrays?
It could be the case that you are over-releasing the NSStrings you are adding to the cellArrays.
Related
I'm trying to create a "wrapping" like effect for text around an image that has set dimensions.
___________
........|
........| image
label.1.|
........|___________
....................
.......label.2......
....................
....................
Here is the method im using right now:
- (NSArray *)splitString:(NSString*)str maxCharacters:(NSInteger)maxLength { //this will split the string to add to two UILabels
NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:1];
NSArray *wordArray = [str componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSInteger numberOfWords = [wordArray count];
NSInteger index = 0;
NSInteger lengthOfNextWord = 0;
while (index < numberOfWords) {
NSMutableString *line = [NSMutableString stringWithCapacity:1];
while ((([line length] + lengthOfNextWord + 1) <= maxLength) && (index < numberOfWords)) {
lengthOfNextWord = [[wordArray objectAtIndex:index] length];
[line appendString:[wordArray objectAtIndex:index]];
index++;
if (index < numberOfWords) {
[line appendString:#" "];
}
}
[tempArray addObject:line];
}
return tempArray;
}
I give it the maxCharacters value of where I want to split the text, which is the max height of the first UILabel. This method is essentially what I want, but sometimes the last line of the first UILabel is "higher" than others leaving a gap between the first UILabel and the second UILabel.
Here is how I use the method:
NSArray *splitStringArray = [self splitString:eventRecord.summary maxCharacters:280];
UILabel *firstSumValue = [[UILabel alloc] init];
NSString *firstSumString = [splitStringArray objectAtIndex:0];
CGSize maxFirstSumSize = CGSizeMake(185.0,150.0);
UIFont *firstSumFont = [UIFont fontWithName:#"HelveticaNeue-Bold" size:12];
CGSize firstSumStringSize = [firstSumString sizeWithFont:firstSumFont
constrainedToSize:maxFirstSumSize
lineBreakMode:firstSumValue.lineBreakMode];
CGRect firstSumFrame = CGRectMake(10.0, presentedValue.frame.origin.y + presentedValue.frame.size.height, 185.0, firstSumStringSize.height);
firstSumValue.frame = firstSumFrame;
firstSumValue.font = [UIFont fontWithName:#"HelveticaNeue" size:12];
firstSumValue.lineBreakMode = UILineBreakModeWordWrap;
firstSumValue.numberOfLines = 0 ;
[self.mainScrollView addSubview:firstSumValue];
firstSumValue.text = [splitStringArray objectAtIndex:0];
UILabel *secondSumValue = [[UILabel alloc] init];
NSInteger isSecond = 0; //no
if([splitStringArray count] > 1){
isSecond = 1; //yes
NSString *secondSumString = [splitStringArray objectAtIndex:1];
CGSize maxSecondSumSize = CGSizeMake(310.0,9999.0);
UIFont *secondSumFont = [UIFont fontWithName:#"HelveticaNeue-Bold" size:12];
CGSize secondSumStringSize = [secondSumString sizeWithFont:secondSumFont
constrainedToSize:maxSecondSumSize
lineBreakMode:secondSumValue.lineBreakMode];
CGRect secondSumFrame = CGRectMake(10.0, firstSumValue.frame.origin.y + firstSumValue.frame.size.height, 310.0, secondSumStringSize.height);
secondSumValue.frame = secondSumFrame;
secondSumValue.font = [UIFont fontWithName:#"HelveticaNeue" size:12];
secondSumValue.lineBreakMode = UILineBreakModeWordWrap;
secondSumValue.numberOfLines = 0 ;
[self.mainScrollView addSubview:secondSumValue];
secondSumValue.text = [splitStringArray objectAtIndex:1];
}
How do I keep everything consistent and aligned properly. Perhaps, there is a better method one could recommend. Not core text because it's out of my scope of knowledge.
Consider using a UIWebView instead, with the layout defined in a local HTML file. It can save you a lot of headache rather than trying to deal with complex layouts by hand.
I am trying to add elements to a scroll view using this code:
int missionCount;
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSDictionary *missionsDict = [responseString JSONValue];
/*NSArray *luckyNumbers = [json objectWithString:responseString error:&error];*/
NSLog(#"user Info array is: %#", missionsDict);
// NSDictionary *array = [luckyNumbers1 objectForKey:#"data"];
NSDictionary *missionsData;
missionsData = [missionsDict objectForKey:#"data"];
NSLog(#"missionsData is: %#", missionsData);
NSEnumerator *inner = [missionsData objectEnumerator];
missionsScroll.contentSize = CGSizeMake(768, 1005);
id value;
int badgeY1;
int badgeY2;
int badgeY3;
badgeY1 = 146;
badgeY2 = 188;
badgeY3 = 188;
while((value = [inner nextObject])) {
NSLog(#"value is: %#", value);
NSLog(#"progress is: %#", [value objectForKey:#"progress"]);
NSLog(#"user Info array is: %#", missionsDict);
NSLog(#"name is: %#",[value objectForKey:#"reward_definitions"]);
NSLog(#"missionsData is: %#", missionsData);
NSDictionary *moreData;
moreData = [value objectForKey:#"reward_definitions"];
NSEnumerator *inner2 = [moreData objectEnumerator];
id value2;
int badgeX;
int badgeCount;
badgeX = 0;
badgeCount = 0;
while((value2 = [inner2 nextObject])) {
UIProgressView *progressView;
progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(323, badgeY1, 372, 9)];
float progressValue;
progressValue = ([[[value objectForKey:#"progress"] objectForKey:#"earned"] floatValue] / [[[value objectForKey:#"progress"] objectForKey:#"possible"] floatValue]);
NSLog(#"progressValue is: %f", progressValue);
[progressView setProgress:progressValue];
[missionsScroll addSubview:progressView];
UILabel *missionName;
missionName = [[UILabel alloc] initWithFrame:CGRectMake(66, badgeY1, 227, 21)];
missionName.backgroundColor = [UIColor clearColor];
missionName.textColor = [UIColor whiteColor];
missionName.font = [UIFont fontWithName:#"Heiti TC" size:23.0];
missionName.text = [value objectForKey:#"name"];
[missionsScroll addSubview:missionName];
UILabel *requirementsLabel;
requirementsLabel = [[UILabel alloc] initWithFrame:CGRectMake(66, badgeY2+25, 227, 21)];
requirementsLabel.backgroundColor = [UIColor clearColor];
requirementsLabel.textColor = [UIColor whiteColor];
requirementsLabel.font = [UIFont fontWithName:#"Papyrus" size:19];
requirementsLabel.text = #"To complete you need:";
[missionsScroll addSubview:requirementsLabel];
NSLog(#"Image URL is: %#", [value2 objectForKey:#"image_url"]);
NSURL *url1 = [NSURL URLWithString: [NSString stringWithFormat:#"%#", [value2 objectForKey:#"image_url"]]];
NSData *urlData1 = [NSData dataWithContentsOfURL:url1];
UIImage *image1 = [UIImage imageWithData:urlData1];
UIImageView *badge = [[UIImageView alloc] initWithImage:image1];
[badge setFrame:CGRectMake(badgeX, badgeY2+70, 70, 70)];
[missionsScroll addSubview:badge];
[badge release];
badgeCount = badgeCount+1;
NSLog(#"badgeCount is: %i", badgeCount);
if (badgeCount == 4) {
NSLog(#"Badge Count = 4");
badgeY2 = badgeY2 +70;
badgeX = 0;
badgeCount = 0;
} else {
NSLog(#"Badge Count ≠ 4");
badgeX = badgeX +75;
}
}
NSLog(#"1st While loop done");
// NSLog(#"reward_definitions is: %#", [missionsData objectForKey:#"id"]);
// NSLog(#"Image URL is: %#", [[value objectForKey:#"reward_definitions"] objectForKey:#"image_url"]);
//if ( [array isKindOfClass:[NSDictionary class]] ) {
badgeY1 = badgeY1 +200;
badgeY2 = badgeY2 +200;
badgeY3 = badgeY3 +200;
missionCount = missionCount+1;
}
NSLog(#"While loops done");
for (int a; missionCount > 4; a = a+1) {
missionsScroll.contentSize = CGSizeMake(776, missionsScroll.contentSize.height+200);
}
Nothing is showing up in the scroll view.
It's not obvious what is happening, but first things to check are where the views are valid (not nil) and that this code is running on the main thread.
Put these in and post the results.
NSLog(#"missionsScroll: %#", (missionsScroll==nil)?#"NIL":#"OK");
NSLog(#"progressView: %#", (progressView==nil)?#"NIL":#"OK");
NSLog(#"missionName: %#", (missionName==nil)?#"NIL":#"OK");
NSLog(#"mainThread: %#", ([NSThread isMainThread])?#"OK":#"Background Thread");
Your code is quite convoluted and very difficult to read. Perhaps you could check if your complicated coordinates calculations work as expected, e.g.
NSLog(#"Frame of badge %#", NSStringFromCGRect(badge.frame));
How many times are your while loops iterating? The outer loop increases the y-position of your labels. But the labels will only be displayed at the end of the run loop / start of the next run loop. If you exit this method with the labels with a high y-value then you'll not see them. (It doesn't matter how many times you change the y-value while you're running this code. The display will only update when it's all done.)
** Correction ** You seem to be adding new views each time around your while loop. So in fact I'd expect you to have multiple copies of the subviews appearing when they finally get displayed.
(There's a lot of code to wade through here. If my answer is way off, you might get better answers, but trimming back some of the code and isolating the issue.)
I have a method to generate a Deck object (NSObject subclass with an NSMutableArray property) and it populates the array with Card objects (UIView subclass with some integer and one NSString property). When I ask for a Deck I check to see if one already exists (I think) and if so, release it before getting a new one.
The code from my viewcontroller...
#import "FlashTestViewController.h"
#implementation FlashTestViewController
- (IBAction)generateDeck {
if (aDeck != nil) {
[aDeck release];
}
aDeck = [[Deck alloc] initDeckWithOperator:#"+"];
}
- (IBAction)generateCard {
if (aCard != nil) {
[aCard fadeAway];
}
aCard = [aDeck newCardFromDeck];
[self.view addSubview:aCard];
}
- (void)fadeAway {
[aCard removeFromSuperview];
[aCard release];
}
#end
The Deck class is as follows...
#import <Foundation/Foundation.h>
#import "Card.h"
#class Deck;
#interface Deck : NSObject {
NSMutableArray* cards;
}
#property(nonatomic, retain) NSMutableArray* cards;
- (id)initDeckWithOperator: (NSString*)mathOper;
- (id)newCardFromDeck;
#end
- (id)initDeckWithOperator: (NSString*)mathOper {
if (cards != nil) {
[cards release];
}
cards = [[NSMutableArray alloc] init];
for (int i=0; i<11; i++) {
for (int j=0; j<11; j++) {
int xPos = (random() % 220) + 10;
int yPos = (random() % 360) + 10;
Card* aCard = [[Card alloc] initWithFrame:CGRectMake(xPos, yPos, 60, 80)];
aCard.upperOperand = i;
aCard.lowerOperand = j;
aCard.theOperator = mathOper;
aCard.theResult = i + j;
UITextView* upperTextView = [[UITextView alloc] initWithFrame:CGRectMake(5, 5, 50, 20)];
NSString* upperOper = [[NSString alloc] initWithFormat:#" %d", i];
upperTextView.text = upperOper;
[aCard addSubview:upperTextView];
[upperTextView release];
[upperOper release];
UITextView* middleTextView = [[UITextView alloc] initWithFrame:CGRectMake(5, 30, 50, 20)];
NSString* middleOper = [[NSString alloc] initWithFormat:#"%# %d", mathOper, j];
middleTextView.text = middleOper;
[aCard addSubview:middleTextView];
[middleTextView release];
[middleOper release];
UITextView* lowerTextView = [[UITextView alloc] initWithFrame:CGRectMake(5, 55, 50, 20)];
NSString* lowerOper = [[NSString alloc] initWithFormat:#" %d", j+i];
lowerTextView.text = lowerOper;
[aCard addSubview:lowerTextView];
[lowerTextView release];
[lowerOper release];
[cards addObject: aCard];
[aCard release];
}
}
return self;
}
- (id)newCardFromDeck {
int index = random() % [cards count];
Card* selectedCard = [[cards objectAtIndex:index] retain];
[cards removeObjectAtIndex:index];
return selectedCard;
}
#end
I do the same thing when I ask for a new card from the newCardFromDeck method and it works. Any suggestions?
Thanks!
Add this code to your Deck.m file:
- (void)dealloc
{
[cards release];
[super dealloc];
}
Looking at this line of code:
cards = [[NSMutableArray alloc] init];
Do you release cards in your dealloc method? It looks like this could potentially be a memory leak.
aDeck in generateDeck is also be a leak if you don't release it in the view's dealloc.
In newCardFromDeck:
Card* selectedCard = [[cards objectAtIndex:index] retain];
looks like you retain the card and return it somewhere. Where does this return value end up? If it ends up in another variable with a 'retain' property on it, it can get retained a second time (upon assignment to the variable).
In my iPhone Project when i select build and analyze (shift + mac + A ) it will give me all potential memory leak in my project... but in my current project it is not working... when i intentionally put a memory leak and select build and analyze... it doesn't give me any potential memory leak as analyzer result
if i write
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:6];
NSMutableArray *tempArrayfinal = [[NSMutableArray alloc] initWithCapacity:12];
and doesn't release it... it is not giving me any potential leak but if i write
NSString *leakyString = [[NSString alloc] initWithString:#"Leaky String "];
NSLog(#"%#",leakyString);
here it gives me potential leak as analyzer result...why it is not giving potential leak in NSMutableArray and why it gives potential leak in NSString ?... how can i rely on Build and analyze for memory leak...
I've run the app with Leak tool and it is showing me leak in tempArray and tempArrayfinal
Here is my function
- (void)viewDidLoad
{
[super viewDidLoad];
maxOnSnaxAppDelegate *delegate = (maxOnSnaxAppDelegate *)[[UIApplication sharedApplication] delegate];
lblMessage.tag = MESSAGE_LABEL;
lblGuess.tag = GUESS_LABEL;
lblScore.tag = SCORE_LABEL;
self.gameCompleteView.tag = FINAL_SCORE_VIEW;
lblFinalScore.tag = FINAL_SCORE_LABEL;
lblGuess.text = #"";
lblMessage.text = #"";
lblScore.text = #"";
int row = 0;
int column = 0;
maxImagrArray = [[NSMutableArray alloc] init];
for(UIView *subview in [self.view subviews]) {
if([subview isKindOfClass:[CustomImageView class]])
{
[subview removeFromSuperview];
}
}
for(int i = 0 ; i < 12 ; i++)
{
if(i%3 == 0 && i != 0)
{
row++;
column = -1;
}
if(i != 0 )
{
column++;
//row = 0;
}
CustomImageView *tempImageView = [[CustomImageView alloc] initWithImage:[UIImage imageNamed:#"max-img.png"]];
tempImageView.frame = CGRectMake((column*tempImageView.frame.size.width) + 45, (row*tempImageView.frame.size.height)+ 60, tempImageView.frame.size.width, tempImageView.frame.size.height);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, tempImageView.bounds);
[self.view addSubview:tempImageView];
tempImageView.tag = i+1;
tempImageView.userInteractionEnabled = YES;
[maxImagrArray addObject:tempImageView];
[tempImageView setIndex:i];
[tempImageView release];
}
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:6];
NSMutableArray *tempArrayfinal = [[NSMutableArray alloc] initWithCapacity:12];
for(int i = 0 ; i < 12 ; i++)
{
if(i < 6)
{
int temp = (arc4random() % 10) + 1;
NSString *tempStr = [[NSString alloc] initWithFormat:#"%d",temp];
[tempArray insertObject:tempStr atIndex:i];
[tempArrayfinal insertObject:tempStr atIndex:i];
[tempStr release];
}
else
{
int temp = (arc4random() % [tempArray count]);
[tempArrayfinal insertObject: (NSString *)[tempArray objectAtIndex:temp] atIndex:i];
//int index = [(NSString *)[tempArray objectAtIndex:temp] intValue];
[tempArray removeObjectAtIndex:temp];
}
CustomImageView *tmpCustom = [maxImagrArray objectAtIndex:i];
tmpCustom.frontImageIndex = [(NSString *)[tempArrayfinal objectAtIndex:i] intValue];
NSLog(#"%d",tmpCustom.frontImageIndex);
}
[maxImagrArray release];
delegate.time = 60.0;
timer = nil;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countDown) userInfo:nil repeats:YES];
delegate.view = self.view;
//[tempArray release];
//[tempArrayfinal release];//these 2 lines are deliberately commented to see
//...it is not showing any potential memory leak though....
delegate.viewController = self;
}
please help...
[tempArray insertObject:tempStr atIndex:i];
[tempArrayfinal insertObject:tempStr atIndex:i];
are the culprits... when i uncomment these 2 lines.. it stops giving me the warning... i don't know why...
You shouldn't really rely on the Build and Analyze tool. It does not always catch all leaks. Threre is no substitute for following the memory management rules from apple (apart from garbage collection on OS X). However, I'm not sure why it isn't catching such a simple leak. I tried at line in a method and it did give me a result. Are you sure its not in an if statement, because I've found that sometimes in an if statement it won't correct you.
i want create image animation , i have 50 images with png format now i want set images name ... something like this but doesnt work !
my images name are : iamge_0000 to image_0050
pasheAnimation.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"pashe_0000.png"],nil];
[pasheAnimation setAnimationRepeatCount:5];
pasheAnimation.animationDuration = 4;
[pasheAnimation startAnimating];
??!?!?!?
jason Code [EDITED] :
NSMutableArray* myImages = [[[NSMutableArray alloc] initWithCapacity:607] autorelease];
for( int i = 1; i <= 607; i++ ) {
[myImages addObject:[UIImage imageNamed:[NSString stringWithFormat:#"p%d.png",i]]];
}
butterflyView.animationImages = myImages;
[butterflyView setAnimationRepeatCount:100];
butterflyView.animationDuration = 0;
[butterflyView startAnimating];
// There are actually 51 images in this series (0000-0050)
NSMutableArray* myImages = [[[NSMutableArray alloc] initWithCapacity:51] autorelease];
for( int i = 0; i <= 50; i++ ) {
[myImages addObject:[UIImage imageNamed:[NSString stringWithFormat:#"image_%04d.png", i]]?:[NSNull null]];
}
You actually have 51 images, from zero to fifty.
NSMutableArray *myImages = [NSMutableArray arrayWithCapacity:51];
for (NSUInteger idx = 0; idx <= 50; idx++) {
NSString *filename = [NSString stringWithFormat:"image_%04d.png", idx];
UIImage *image = [UIImage imageNamed:filename];
if (image) {
[myImages addObject:image];
}
else {
NSLog(#"Could not add %#", filename); // could also throw exception, if you want
}
}