My code below is causing my app to quit i.e. get black screen and then see in debugger console: Program received signal: “0”.
Basically it is causing problem when my orderArray has count of 2000 or more. I am using iPhone 3GS with iOS 4.2
Question: Is there a more efficient and less memory consuming way to create my long outStr?
NSString *outStr = #"";
for (int i = 0; i < count; i++) {
NSDictionary *dict = [[ARAppDelegate sharedAppDelegate].orderArray objectAtIndex:i];
outStr = [outStr stringByAppendingFormat:#"%#,%#,%#,%#\n",
[dict valueForKey:#"CODE"],
[dict valueForKey:#"QTY"],
[[ARAppDelegate sharedAppDelegate].descDict valueForKey:[dict valueForKey:#"CODE"]],
[[ARAppDelegate sharedAppDelegate].priceDict valueForKey:[dict valueForKey:#"CODE"]]];
}
Update: Thanks to very kind people who helped, below is my modified code:
NSArray *orderA = [ARAppDelegate sharedAppDelegate].orderArray;
NSDictionary *descD = [ARAppDelegate sharedAppDelegate].descDict;
NSDictionary *priceD = [ARAppDelegate sharedAppDelegate].priceDict;
NSMutableString *outStr = [[[NSMutableString alloc] init] autorelease];
for (int i = 0; i < [orderA count]; i++) {
NSDictionary *dict = [orderA objectAtIndex:i];
NSString *code = [dict valueForKey:#"CODE"];
[outStr appendFormat:#"%#,%#,%#,%#\n",
code,
[dict valueForKey:#"QTY"],
[descD valueForKey:code],
[priceD valueForKey:code]];
}
[self emailTxtFile:[NSString stringWithString:outStr]];
// This reaches end of method
The problem is that in every iteration a new string object is formed. This consumes a lot of memory. One solution could be to use a local autoreleasepool, but that's rather complicated here.
You should use an NSMutableString, like:
NSMutableString *outStr = [[[NSMutableString alloc] init] autorelease];
for (int i = 0; i < count; i++) {
NSDictionary *dict = [[ARAppDelegate sharedAppDelegate].orderArray objectAtIndex:i];
[outStr appendFormat:#"%#,%#,%#,%#\n",
[dict valueForKey:#"CODE"],
[dict valueForKey:#"QTY"],
[[ARAppDelegate sharedAppDelegate].descDict valueForKey:[dict valueForKey:#"CODE"]],
[[ARAppDelegate sharedAppDelegate].priceDict valueForKey:[dict valueForKey:#"CODE"]]];
}
Then you can use outStr, just as if it was an NSString. As Tom points out in the comments, you could turn the NSMutableString into an NSString when you're finished, using:
NSString *result = [NSString stringWithString:outStr];
[outStr release]; // <-- add this line and remove the autorelease
// from the outStr alloc/init line
making your code re-usable and easier to maintain.
Related
I found a workaround myself, but still trying to understand the problem.
I created a Autocomplete text field with the use of uitableview which is hidden until textfield is edited. The UI part works fine. It's the searching for the results part that's the problem. I declared a local NSMutableDictionary to store my results because I wanted the results to be sorted by the key's values.
if I call keysSortedByValueUsingSelector on the dictionary directly, it crashes. However if I get the keys by [dict allKeys] first, then call sortedArrayUsingSelector, it works fine:
// This commented out line will crash
// NSArray *sortedKeysArray = [dict keysSortedByValueUsingSelector:#selector(compare:)];
// The next two lines runs fine.
NSArray *keyArray = [dict allKeys];
NSArray *sortedKeysArray = [keyArray sortedArrayUsingSelector:#selector(compare:)];
Here is the complete source code for the search method:
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring
{
// Put anything that starts with this substring into the autocompleteUrls array
// The items in this array is what will show up in the table view
[autocomplete_symbol_array removeAllObjects];
rRSIAppDelegate *appDelegate = (rRSIAppDelegate *)([[UIApplication sharedApplication] delegate]);
NSString *input_str = [substring uppercaseString];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
int i = 0;
for(SymbolInfo *symbol_info in appDelegate.m_symbol_info_array)
{
i++;
NSString *info_str = [[[symbol_info.m_symbol uppercaseString] stringByAppendingString:#"|"] stringByAppendingString:[symbol_info.m_company_name uppercaseString]];
NSUInteger pos = [info_str rangeOfString:input_str].location;
if (pos != NSNotFound)
{
int tmp = pos * 10000 + i;
NSNumber *map_key = [[NSNumber alloc] initWithInt:tmp];
[dict setObject:symbol_info forKey:map_key];
}
}
// This commented out line will crash
// NSArray *sortedKeysArray = [dict keysSortedByValueUsingSelector:#selector(compare:)];
// The next two lines runs fine.
NSArray *keyArray = [dict allKeys];
NSArray *sortedKeysArray = [keyArray sortedArrayUsingSelector:#selector(compare:)];
for (NSNumber *key in sortedKeysArray)
{
SymbolInfo *symbol_info = [dict objectForKey:key];
[autocomplete_symbol_array addObject:symbol_info];
}
// NSLog(#"everything added: %d", [autocomplete_symbol_array count]);
[autocompleteTableView reloadData];
}
The NSMutableDictionary's method is:
- (void)setObject:(id)anObject forKey:(id < NSCopying >)aKey;
This means that the key should implement the NSCopying protocol.
I am doing json parsing application. In which there is not an issue regarding parsing. I am having list uptill the type="0". But type="1" is having a description. All the "listing" as well as the "description" is set properly.
{"pageid":"5824","title":"Sms Collection","type":"0","desc":"Friendship SMS:$#|5825|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;Love SMS:$#|5826|#$:4cing.com/mobile_app/uploads/pageicon/Love.png;Miss U SMS:$#|5827|#$:4cing.com/mobile_app/uploads/pageicon/missu.png;Funny SMS:$#|5828|#$:4cing.com/mobile_app/uploads/pageicon/funny.png;Valentine SMS:$#|5829|#$:4cing.com/mobile_app/uploads/pageicon/valantine.png;Adult SMS:$#|5830|#$:4cing.com/mobile_app/uploads/pageicon/adult.png;Anniversary SMS:$#|5832|#$:4cing.com/mobile_app/uploads/pageicon/anniversary.png;Birthday SMS:$#|5833|#$:4cing.com/mobile_app/uploads/pageicon/birthday.png;Break up SMS:$#|5834|#$:4cing.com/mobile_app/uploads/pageicon/Breakup.png;Broken Heart SMS:$#|5835|#$:4cing.com/mobile_app/uploads/pageicon/heartbroken.png;Christmas SMS:$#|5836|#$:4cing.com/mobile_app/uploads/pageicon/Christmas.png;Exam SMS:$#|5837|#$:4cing.com/mobile_app/uploads/pageicon/exam.png;Flirt SMS:$#|5838|#$:4cing.com/mobile_app/uploads/pageicon/flirtsms.png;Good Luck SMS:$#|5839|#$:4cing.com/mobile_app/uploads/pageicon/goodluck.png;Good Morning SMS:$#|5840|#$:4cing.com/mobile_app/uploads/pageicon/goodmornig.png;Good Night SMS:$#|5841|#$:4cing.com/mobile_app/uploads/pageicon/goodnight.png;Insult SMS:$#|5842|#$:4cing.com/mobile_app/uploads/pageicon/inseart.png;Pashto SMS:$#|5843|#$:4cing.com/mobile_app/uploads/pageicon/pashto.png;Poetry SMS:$#|5844|#$:4cing.com/mobile_app/uploads/pageicon/poetry.png;Sardar SMS:$#|5845|#$:4cing.com/mobile_app/uploads/pageicon/sardar.png;Santa Banta SMS:$#|5846|#$:4cing.com/mobile_app/uploads/pageicon/santabanta.png;Smile SMS:$#|5847|#$:4cing.com/mobile_app/uploads/pageicon/smile.png;Sorry SMS:$#|5848|#$:4cing.com/mobile_app/uploads/pageicon/sorry.png;Chanakya SMS:$#|5849|#$:4cing.com/mobile_app/uploads/pageicon/chanakya.png;","cache":"1","Nexturl":"5825","prevurl":"0","bckurl":"0"}
when application is launched (type="0") this is the first list with above data.
Onclick of Friendship SMS cell i am getting (type="0") this data.
{"pageid":"5825","title":"Friendship SMS","type":"0","desc":"Do not lie, Do not cheat and do not make promises :$#|5850|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;There are no strings attached to a friendship, no :$#|5851|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;friends are like stars. You ca not always see them:$#|5852|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;Friends should b like zero. when u add, they r sam:$#|5853|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;Friendship is like a glass handle it with care bec:$#|5854|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;A friend gives hope when life is low, a friend is :$#|5855|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;How long shall we be friends? Do you want a clue? :$#|5856|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;My friendship is nothing but a round, Wandering wh:$#|5857|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;When nails are growing, We cut our nails, Not fing:$#|5858|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;A true friend understands when u say I forgot, wai:$#|5859|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;Making a million friends is not an achievement, Th:$#|5860|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;Friendship and Medicine both r good 4 our health:$#|5861|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;A memory lasts forever, and never does it die. Tru:$#|5862|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;Where there is no compromise in telling the secret:$#|5863|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;I m not Wealthy but i have Rich Heart, I m not Bes:$#|5864|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;Do not Love a Friend who Hurts U Do not Hurt a Fri:$#|5865|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;To hear what is unspoken, to see what is invisible:$#|5866|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;Life is 5 star Mother is top star Father is king s:$#|5867|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;A single rose can be my garden A single friend, my:$#|5868|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;To live a life i need heartbeat, 2 have heartbeat :$#|5869|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;A true relationship is when you can tell each othe:$#|5870|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;Friends\" are like balloons once u let them go u ca:$#|5871|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;MY friendship is just like a rubber band, It is to:$#|5872|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;I wish every relationship come with the same tag a:$#|5873|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;As precious as u r to me, As precious no one can e:$#|5874|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;Friendship Must Never Be Buried Under The Weight O:$#|5875|#$:4cing.com/mobile_app/uploads/pageicon/friendship.png;","cache":"1","Nexturl":"5850","prevurl":"5824","bckurl":"5849"}
Finally this is having (type="1") for the screen onclick of "Do not lie,Do not che..."
So description is shown as
I am having problem in the back process, i have to use prevurl which is similar to the pageid of rhe previous page, for the back functionality
This is the code which i am doing for the back functionality,
-(IBAction)btnBackClicked:(id)sender
{
int Type;
NSMutableDictionary *tempDict1;
for(int i=0;i<[test.JsonPageList count];i++)
{
tempDict1 = [[NSMutableDictionary alloc]init];
tempDict1 = (NSMutableDictionary *)[test.JsonPageList objectAtIndex:i];
NSLog(#"pageid is.....%d",[[tempDict1 valueForKey:#"pageid"] intValue]);
if ([[tempDict1 valueForKey:#"pageid"] intValue])
{
Type = [[tempDict1 valueForKey:#"type"] intValue];
if (Type == 0)
{
NSArray *arr=[[tempDict1 valueForKey:#"desc"] componentsSeparatedByString:#";"];
NSString *subStar = #"|#$:";
NSString *sub=#":$#|";
[test.arrTitle removeAllObjects];
[test.arrnew removeAllObjects];
[test.arrId removeAllObjects];
[test.arrImages removeAllObjects];
for (int i=0; i<[arr count]-1; i++)
{
[test.arrTitle addObject:[[arr objectAtIndex:i] substringToIndex:NSMaxRange([[arr objectAtIndex:i] rangeOfString:sub])-4]];
[test.arrnew addObject:[[arr objectAtIndex:i] substringFromIndex:NSMaxRange([[arr objectAtIndex:i] rangeOfString:sub])]];
[test.arrId addObject:[[test.arrnew objectAtIndex:i] substringToIndex:NSMaxRange([[test.arrnew objectAtIndex:i] rangeOfString:subStar])-4]];
[test.arrImages addObject:[[arr objectAtIndex:i] substringFromIndex:NSMaxRange([[arr objectAtIndex:i] rangeOfString:subStar])]];
}
[tbl_withData reloadData];
}
}
}
}
This is the code for the parsing
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"SecondTime"])
{
[self saveData:responseData toFile:#"SMSCollection.txt"];
results = [responseString JSONValue];
JsonPageList = [results objectForKey:#"page"];
desc = [[NSMutableArray alloc] init];
for (NSString * strName in results)
{
JsonPageList = [results objectForKey:strName];
dictHash = [[NSMutableDictionary alloc] init];
[dictHash setObject:JsonPageList forKey:#"JsonPageList"];
for (int i = 0; i < [JsonPageList count]; i++)
{
[desc addObject:[[JsonPageList objectAtIndex:i] valueForKey:TAG_DESC]];
int PAGEID = [[NSString stringWithFormat:#"%#",[[JsonPageList objectAtIndex:i] valueForKey:#"pageid"]] intValue];
[self displayPage:PAGEID];
}
}
}
[responseString release];
}
-(void) displayPage:(int)pageID
{
page.pageid = pageID;
if (page.type == PAGE_TYPE_MENU)
{
NSString *desc1=[desc objectAtIndex:0];
NSArray *arr=[desc1 componentsSeparatedByString:#";"];
NSString *subStar = #"|#$:";
NSString *sub=#":$#|";
arrTitle=[[NSMutableArray alloc] init];
arrImages = [[NSMutableArray alloc] init];
arrnew = [[NSMutableArray alloc]init];
arrId=[[NSMutableArray alloc]init];
for (int i=0; i<[arr count]-1; i++)
{
[arrTitle addObject:[[arr objectAtIndex:i] substringToIndex:NSMaxRange([[arr objectAtIndex:i] rangeOfString:sub])-4]];
[arrnew addObject:[[arr objectAtIndex:i] substringFromIndex:NSMaxRange([[arr objectAtIndex:i] rangeOfString:sub])]];
[arrId addObject:[[arrnew objectAtIndex:i] substringToIndex:NSMaxRange([[arrnew objectAtIndex:i] rangeOfString:subStar])-4]];
[arrImages addObject:[[arr objectAtIndex:i] substringFromIndex:NSMaxRange([[arr objectAtIndex:i] rangeOfString:subStar])]];
}
}
else if (page.type == PAGE_TYPE_CONTENT)
{
NSLog(#"CURR title:- %#\n & desc:- %#",page.title1 ,page.desc);
UITextView *TextView = [[UITextView alloc] init];
TextView.text = page.title1;
UILabel *lblcurrentPage = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 300)];
lblcurrentPage.backgroundColor = [UIColor whiteColor];
lblcurrentPage.textColor = [UIColor blackColor];
lblcurrentPage.text = page.desc;
}
}
Help me out of this problem.
Im trying to replace the 7th index of the array "lines2". The NSMUTABLEARRAY "lines2" is derived from the UNIX command "ps aux", and I suspect that this command returns an array of NSCFStrings. Im basically trying to replace "Ss" with "Ss (Running)" for now. The problem is that I get a SIGABRT error every time The program reaches the part where it tries to replace the particular array element. The code for my viewController is below.
NSLog(#"myString is :%#", myString);
int processID = [myString intValue];
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/ps"];
arguments = [NSArray arrayWithObjects: #"aux", [NSString stringWithFormat:#"%i", processID],nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
//[task setStandardOutput: pipe];
[task setStandardOutput:pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *string;
string = [[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding];
// NSLog(#"%#",string);
NSArray *lines= [string componentsSeparatedByString:#"\n"];
NSString *lastline = [lines objectAtIndex:[lines count]-2];
// NSLog(#"%#",lastline);
lines2= [lastline componentsSeparatedByString:#" "];
NSLog(#"%#",lines2);
for (int i=0; i<[lines2 count]; i++) {
if([[lines2 objectAtIndex:i] isEqualToString:#""]){
[lines2 removeObjectAtIndex:i];
}
}
for (int i=0; i<[lines2 count]; i++) {
if([[lines2 objectAtIndex:i] isEqualToString:#""]){
[lines2 removeObjectAtIndex:i];
}
}
for (int i=0; i<[lines2 count]; i++) {
if([[lines2 objectAtIndex:7] isEqualToString:#"Ss"]){
[[lines2 objectAtIndex:0] replaceObjectAtIndex:7 withObject:#"SS (Running)"];
}
}
Any help is very much appreciated!
Please look at the documentation for the method -componentsSeparatedByString:. The signature is:
- (NSArray *)componentsSeparatedByString:(NSString *)separator
Notice the return type is NSArray. This is an immutable object. You must not change it even if inspecting the returned object (say with a debugger or an NSLog) shows it to actually be mutable. You must respect the API contract. (Read the section of the link entitled "receiving mutable objects".)
That said, the immediate cause of your error is this line:
[[lines2 objectAtIndex:0] replaceObjectAtIndex:7 withObject:#"SS (Running)"];
^^^^^^^^^^^^^^^^^^^^^^^^ This is wrong
lines2 is an array of strings. [lines2 objectAtIndex: 0] is a string. Why are you sending -replaceObjectAtIndex:withObject: to it?
You don't say what the error you're seeing is, but you cannot change the values in the NSArray because an NSArray is an immutable container.
Use an NSMutableArray when you want to make modifications. If you have an NSArray already (as in the return value from -componentsSeparatedByString:), you can get a mutable array by doing this:
NSMutableArray * myMutableArray = [NSMutableArray arrayWithArray:lines2];
NSArray is not mutable. First copy it to an NSMutableArray (e.g. using [NSMutableArray arrayWithArray:]) so you can manipulate it.
Didn't you get any warnings during compilation?
The following code should add different objects to an NSMutableArray however it adds the same object each time:-
for(int i =0; i < [results count];i++)
{
Reservation *r = [[Reservation alloc] init];
NSDictionary *dict = [results objectAtIndex: i];
r.resId = [dict objectForKey:#"reservationrequest_id"];
r.driver = [dict objectForKey:#"driver_name"];
r.vehicle = [dict objectForKey:#"billing_registration"];
r.startDate = [dict objectForKey:#"hire_from_date"];
r.endDate = [dict objectForKey:#"hire_to_date"];
r.status = [dict objectForKey:#"status_type"];
[self.bookingsObjectArray addObject:r];
[r release];
r = nil;
}
I have exactly the same code that works fine in another part of my app it just uses a Groups class instead of Reservation.
When debugging the code I found that when it does [r release]; 'r' is greyed out but still keeps the same pointer. When it goes back to Reservation *r = [[Reservation alloc] init];
'r' has the same pointer as last time.
Any ideas what might be causing the problem? Thanks in advance.
Chris
Been running instruments on my app. Its says i am leaking 864bytes & 624bytes from 2 NSCFString and the library responsible is Foundation.
So that leads me to believe thats its not a leak caused by me? Or is it?
Here is the offending method according to instruments. It seems to be a
substringWithRange
that is leaking.
-(void) loadDeckData
{
deckArray =[[NSMutableArray alloc] init];
NSString* path = [[NSBundle mainBundle] pathForResource:#"rugby" ofType:#"txt"
inDirectory:#""];
NSString* data = [NSString stringWithContentsOfFile:path encoding:
NSUTF8StringEncoding error: NULL];
NSString *newString = #"";
NSString *newline = #"\n";
NSString *comma = #",";
int commaCount = 0;
int rangeCount = 0;
NSString *nameHolder = #"";
NSString *infoHolder = #"";
NSMutableArray *statsHolder = [[NSMutableArray alloc] init];
for (int i=0; i<data.length; i++)
{
newString = [data substringWithRange:NSMakeRange(i, 1)];
if ([newString isEqualToString: comma]) //if we find a comma
{
if (commaCount == 0)// if it was the first comma we are parsing the
NAME
{
nameHolder = [data substringWithRange:NSMakeRange(i-
rangeCount, rangeCount)];
}
else if (commaCount == 1)//
{
infoHolder = [data substringWithRange:NSMakeRange(i-
rangeCount, rangeCount)];
//NSLog(infoHolder);
}
else // if we are on to 2nd,3rd,nth comma we are parsing stats
{
NSInteger theValue = [[data
substringWithRange:NSMakeRange(i-rangeCount,rangeCount)]
integerValue];
NSNumber* boxedValue = [NSNumber
numberWithInteger:theValue];
[statsHolder addObject:boxedValue];
}
rangeCount=0;
commaCount++;
}
else if ([newString isEqualToString: newline])
{
NSInteger theValue = [[data substringWithRange:NSMakeRange(i-
rangeCount,rangeCount)] integerValue];
NSNumber* boxedValue = [NSNumber numberWithInteger:theValue];
[statsHolder addObject:boxedValue];
commaCount=0;
rangeCount=0;
Card *myCard = [[Card alloc] init];
myCard.name = nameHolder;
myCard.information = infoHolder;
for (int x = 0; x < [statsHolder count]; x++)
{
[myCard.statsArray addObject:[statsHolder
objectAtIndex:x]];
}
[deckArray addObject:myCard];
[myCard autorelease];
[statsHolder removeAllObjects];
}
else
{
rangeCount++;
}
}
[statsHolder autorelease];
}
Thanks for your advice.
-Code
As Gary's comment suggests this is very difficult to diagnose based on your question.
It's almost certainly a leak caused by you however, I'm afraid.
If you go to the View menu you can open the Extended Detail. This should allow you to view a stack trace of exactly where the leak occurred. This should help diagnose the problem.
When to release deckArray? If deckArray is a class member variable and not nil, should it be released before allocate and initialize memory space?