NSDictionary creation inside loop with ARC - iphone

I'm having a big trouble while creating NSDictionaries inside a for-loop while using ARC. The point is that after the first "dict" creation, the app crashes giving an EXC_BAD_ACCESS so I presume it's something related to the release of the object, but can't figure out what! I tried using an autoreleasepool but the result was the same
for (int i = 0; i < [arr1 count]; i++) {
__strong NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[arr1 objectAtIndex:i], #"name", [arr4 objectAtIndex:i], #"position", [arr2 objectAtIndex:i], #"number", [arr5 objectAtIndex:i], #"status", [[arr6 objectAtIndex:i] intValue], #"order", nil];
[pl_stuff addObject:dict];
}
thanks for your replies

[[arr6 objectAtIndex:i] intValue]
You're trying to add plain integer value to your array, but array accept only objective-c objects. You should probably just leave that as:
[arr6 objectAtIndex:i]

Related

Unable to replace NSArray derived from output of "ps aux" UNIX command

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?

how to create an array of string or float in Objective-C

i need some help here, i need to know how to create an array of string retrieved from an array. i'm using powerplot for graph and it only accept float or string array.
i need to create something something like this dynamically.
NSString * sourceData[7] = {#"2", #"1", #"4", #"8", #"14", #"15", #"10"};
Below are my code to find out the numbers in strings.
NSInteger drunked = [appDelegate.drinksOnDayArray count];
NSMutableArray * dayArray = [[NSMutableArray alloc] init];
NSMutableArray * sdArray = [[NSMutableArray alloc] init];
//float *sdArray[7];
for (int i=0; i<drunked; i++) {
DayOfDrinks *drinksOnDay = [appDelegate.drinksOnDayArray objectAtIndex:i];
NSString * dayString= [NSDate stringForDisplayFromDateForChart:drinksOnDay.dateConsumed];
[dayArray addObject:dayString];
NSLog(#"%#",[dayArray objectAtIndex:i]);
drinksOnDay.isDetailViewHydrated = NO;
[drinksOnDay hydrateDetailViewData];
NSString * sdString= [NSString stringWithFormat:#"%#", drinksOnDay.standardDrinks];
[sdArray addObject:sdString];
NSString *tempstring;
NSLog(#"%#",[sdArray objectAtIndex:i]);
}
thanks for the help :)
Array's in Objectice-C aren't that hard to work with:
NSMutableArray *myArray = [NSMutableArray array];
[myArray addObject:#"first string"]; // same with float values
[myArray addObject:#"second string"];
[myArray addObject:#"third string"];
int i;
int count;
for (i = 0, count = [myArray count]; i < count; i = i + 1)
{
NSString *element = [myArray objectAtIndex:i];
NSLog(#"The element at index %d in the array is: %#", i, element); // just replace the %# by %d
}
You can either use NSArray or NSMutableArray - depending on your needs, they offer different functionality.
Following tutorial covers exactly what you are looking after:
http://www.cocoalab.com/?q=node/19
You can also add the elements to the array when you init (and optionally add them later only if you are using the Mutable version of a collection class:
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:#"2", #"1", #"4", #"8", #"14", #"15", #"10", nil];
[myArray addObject:#"22"];
[myArray addObject:#"50"];
//do something
[myArray release];
You can use malloc to create a C-style array. something like this should work:
NSString **array = malloc(numElements * sizeof(NSString *))
some code here
free(array)
Be aware that unlike NSMutable array, c arrays won't do a retain, so you have to manage it if needed. And don't forget the free

Creating a long NSString causing memory issues

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.

[NSArray subarrayWithRange:]: index 9779 beyond bounds

I am getting the error:
*** -[NSArray subarrayWithRange:]: index 9779 beyond bounds [0 .. 9776]'
***
and I am not sure how to fix it.
If you could tell me that would be great!
NSArray *keys = [NSArray arrayWithObjects:#"type", #"name", #"street", #"address1", #"address2", #"town", #"county", #"postcode", #"number", #"coffee club", #"latitude", #"longitude", nil];
for (int i = 0; i < [chunks count]; i += [keys count])
{
NSArray *subarray = [chunks subarrayWithRange:NSMakeRange(i, [keys count])];
NSDictionary *dict = [[NSDictionary alloc] initWithObjects:subarray forKeys:keys];
NSLog(#"%#", dict);
// do something with dict
[dict release];
}
You don't say what chunks is in your code snippet.
I guess the error is that you are accessing over the bounds of the chunks array.
Maybe something like this would work better:
for (int i = 0; i + [keys count] <= [chunks count]; i += [keys count])
To elaborate a bit more. You are taking a sub array which starts at i and goes to [keys count] more elements, but there is no check that i + [keys count] doesn't go over the chunk array size. Perhaps that's causing a problem?
NSMakeRange does not work this way.
The forst parameter is the starting index and the second is the length of the subarray.
In your case, your code should look like this:
NSArray *subarray = [chunks subarrayWithRange:NSMakeRange(i, [keys count] - i)];
This is why you were getting the "index out of bounds" exception.

Find indices of duplicates in a NSArray

i have an array like
[chapter,indent,left,indent,nonindent,chapter,chapter,indent,indent,left];
i need to find indexes of duplicates and also non duplicate elements .
how to do this...........give some sample code or logic......
thanks in advance
iam using objective c.....
NSArray *myWords = [string componentsSeparatedByString:#"class=\""];
int count_var=[myWords count];
tmp1=#"";
for(int i=1;i<count_var;i++)
{
str=[NSString stringWithFormat:#"\n%#",[myWords objectAtIndex:i]];
class=[str componentsSeparatedByString:#"\""];
NSString *tmp=[NSString stringWithFormat:#"%#",[class objectAtIndex:0]];
tmp1=[[NSString stringWithFormat:#"%#",tmp1] stringByAppendingString:[NSString stringWithFormat:#"%#",tmp]];
}
t1.editable=NO;
t1.text=tmp1;
NSArray *tempo=[[NSArray alloc]init];
tempo=[tmp1 componentsSeparatedByString:#"\n"];
tempCount=[tempo count];
this is my sample code...in this the array tempo contains all objects from that array i want to get index of duplicate strings≥.
You could build a dictionary mapping the objects to index sets. For every index set, a -count of 1 means no duplicates, > 1 means there are duplicates.
NSArray *arr = [NSArray arrayWithObjects:...];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for (NSUInteger i=0; i<[arr count]; ++i) {
id obj = [arr objectAtIndex:i];
NSMutableIndexSet *ids = [dict objectForKey:obj];
if (!ids) {
ids = [NSMutableIndexSet indexSet];
[dict setObject:ids forKey:obj];
}
[ids addIndex:i];
}
NSLog(#"%#", dict);