Replace content of NSMutableArray with NSArray - objective-c

I'm working on an app that needs to retrieve some data from a server. I have created a "Server" class which handles all the communication and has a NSMutableArray *sessionData variable where I would like to store the data coming from the server (btw, is this approach correct?).
I have the data in an NSArray. I would like the NSMutableArray to have the same content of the NSArray but I didn't find any way to do this (sessionData = requestResult).
(subquestion: do I have to initialize in some way the NSMutableArray before using ? I have only declared it with #property and #synthesize)

The code you tried (from the comment) should have worked. The reason it did not work is that your sessionData was nil.
You need to initialize your sessionData - set it to [NSMutableArray array] in the initializer; then your code
[sessionData removeAllObjects];
[sessionData setArray:result];
will work perfectly. You do not even need the first line - the second one replaces the content of sessionData with that of the result.

Try this way:
sessionData = [result mutableCopy];
[result release];
Or
NSMutableArray *sessionData = [[NSMutableArray alloc] initWithContentsOfArray:result];

Or, if you could do this:
NSMutableArray *session = [NSMutableArray arrayWithArray:someArray];

1. is this approach correct?
Yes.
2. I didn't find any way to do this (sessionData = requestResult)
As many have suggested you can use mutableCopy to assign requestResult to sessionData
OR you can use arrayWithArray as one answer suggests.
3. do I have to initialize in some way the NSMutableArray before using ?
Yes. If you are changing any variable it must have memory allocated.

In your example something like this:
NSArray *requestData = [[NSArray alloc] initWithObjects:#"3", #"4", #"5", nil];
_sessionData = [[NSMutableArray alloc] initWithArray:requestData];
[requestData release];
NSLog(#"%#", [sessionData objectAtIndex:0]); // 2012-03-30 15:53:39.446 <app name>[597:f803] 3
NSLog(#"count: %d", [sessionData count]); //2012-03-30 15:53:39.449 <app name>[597:f803] count: 3

Related

Trouble with simple Array - Cocoa

I was wondering to know if there is any possibility to do the following:
I have a method like:
one = [[NSMutableArray alloc] initWithObjects:#"1",#"2",#"3", nil];
two = [[NSMutableArray alloc] initWithObjects:#"4",#"5",#"6", nil];
-(void)getStringAndChooseArray:(NSString *)nameOfArray {
//What i want to do is something like:
NSLog(#"The array %# has got %i objects",nameOfArray,[nameOfArray count])
//Of course it is giving me an error since nameOfArray is a string..
//I know it is hard to understand,
//but what I'm trying to do is to call this method
//pass a string variable, which is named as one of the two arrays,
//and using it to do the rest..
}
How to use a string to identify an array and manipulate it ?
Thanks in advance !
Store your arrays in a dictionary and use the names you want to reference them by as their related keys.
Use a dictionary to map arrays to strings and then you can use them:
one = [[NSMutableArray alloc] initWithObjects:#"1",#"2",#"3", nil];
two = [[NSMutableArray alloc] initWithObjects:#"4",#"5",#"6", nil];
NSDictionary *mapping = [NSDictionary dictionaryWithObjectsAndKeys:#"one",one,#"two",two,nil];
-(void)getStringAndChooseArray:(NSString *)nameOfArray {
NSArray *array = [mapping objectForKey:nameOfArray];
NSLog(#"The array %# has got %i objects",array,[array count])
}

I have a memory leak in this objective-c method, can anyone tell me where?

I'm receiving an exc_bad_access somewhere in the code below. I don't understand where it is if anyone could shine any light on it? It's a method that takes in an NSMutableArray of dictionaries and sorts them by one of the elements in the dictionary. The memory leak is almost certainly in the bit with the block but I think i'm missing something fundamental in finding it...
-(NSMutableArray*)sortBicyclesByDistanceToDevice:(NSMutableArray*)inputArray{
NSArray *arrayToHoldSorted = [[[NSArray alloc] init];
arrayToHoldSorted = [inputArray sortedArrayUsingComparator:^(id a, id b){
NSNumber *first = [[a objectForKey:kDistanceFromDevice] objectForKey:kValue];
NSNumber *second = [[b objectForKey:kDistanceFromDevice] objectForKey:kValue];
return [first compare:second];}];
NSMutableArray *retVal = [[NSMutableArray alloc] init];
retVal = [arrayToHoldSorted mutableCopy];
[arrayToHoldSorted release];
return [retVal autorelease];
}
Thanks
It looks like you assign retVal to an NSMutableArray through then reassign immediately after. The original alloced NSMutableArray will leak. That is:
NSMutableArray *retVal = [[NSMutableArray alloc] init];
retVal = [arrayToHoldSorted mutableCopy];
Should be:
NSMutableArray *retVal = [arrayToHoldSorted mutableCopy];
Replace:
NSMutableArray *retVal = [[NSMutableArray alloc] init];
retVal = [arrayToHoldSorted mutableCopy];
With:
NSMutableArray *retVal = [arrayToHoldSorted mutableCopy];
You are leaking the first value of retVal.
There's more than one in there!
This line:
NSArray *arrayToHoldSorted = [[[NSArray alloc] init];
Is a memory leak since you immediately reassign the pointer. It should be removed. Just declare your array on the next line:
NSArray* arrayToHoldSorted = [inputArray sortedArrayUsingComparator...
This method returns an autoreleased object, so you don't need to release it later on.
A similar pattern with the mutable array. You alloc/init, then overwrite with a new object, giving another leak. Again, remove the alloc/init line and just declare in the next line. mutableCopy gives you an implicitly retained object, so you do need to autorelease it.
You seem to be under the impression that alloc/init is needed every time you declare an object variable. This is not the case.
You allocate arrayToHoldSorted (1) - which you never use as you then get an NSArray back from sortedArrayUsingComparator(2). And then you release it afterwards(3) when you don't own it. You do the same trick for retVal, allocating a NSMutableArray - then overwriting your reference to it by getting a new NSMutableArray from [arrayToHoldSorted mutableCopy];
NSArray *arrayToHoldSorted = [[NSArray alloc] init]; .. // 1
arrayToHoldSorted = [inputArray sortedArrayUsingComparator:^(id a, id b) ..... // 2
[arrayToHoldSorted release]; // 3
Just assign the return NSArray from sortedArrayUsingComparator to a reference...
NSArray* arrayToHoldSorted = [inputArray sortedArrayUsingComparator:^(id a, id b) .....
I think the problem is that in this line:
return [retVal autorelease];
you release something that you have not retained. Also in this line:
NSArray *arrayToHoldSorted = [[[NSArray alloc] init];
you have an extra [, which does not help. But most importantly, you can use the static analyzer in XCode to diagnose this sort of bug, rather than pestering the good folk on StackOverflow.

Add NSStrings to mutable array

I created a mutable array and I have two NSString variables. Now I want to add these two NSStrings to my array. How is this possible? Thanks.
Use the addObject function of you NSMutableArray.
eg.
[myNSMutableArray addObject:myString1];
[myNSMutableArray addObject:myString2];
Jhaliya's answer is correct. +1 vote.
I added a immutable version so you can see the difference. If you dont want to remove or add more objects (NSStrings) to your container, I would recommend using an Immutable version.
Mutable version:
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
NSString *string_one = #"One"];
[mutableArray addObject:string_one];
//Or
[mutableArray addObject:#"Two"];
NSLog(#"%#", mutableArray);
Immutable version
NSArray *immutableArray = [NSArray arrayWithObjects:#"One", #"Two", nil];
NSLog(#"%#", immutableArray);
You can add at NSMutableArray allocation.
Like :
NSMutableArray *test = [NSMutableArray arrayWithObjects:#"test1",#"test2",nil];

Getting an NSString out of an NSArray

I am trying to save and read back some application settings stored as NSStrings in an iPhone app and have been having some trouble.
The code to save looks like:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:accountID];
...
[array writeToFile:[self dataFilePath] atomically:YES];
[array release];
And the code to read looks like (accountID is an NSString*):
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
accountID = [array objectAtIndex:0];
...
[array release];
NSLog(#"Loading settings for: %#", accountID);
The read code throws an exception because after the array is released the accountID variable also appears to have been released (moving the NSLog call before releasing the array works fine). So I'm guessing that I'm creating a reference to the array instead of pulling out the actual string contained in the array. I tried several things to create new strings using the array contents but haven't had any luck.
You guess is on the right lines although you have a reference to the 0th element of the array not the array. The array consists of pointers to NSString objects. The Strings will get get released when yhe array is released.
You need to retain the element you are using e/g/
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
NSString* accountID = [[array objectAtIndex:0]retain];
...
[array release];
NSLog(#"Loading settings for: %#", accountID);
When you release the array the reference to the accountID will also be released. You need to retain it.
accountID = [[array objectAtIndex:0] retain];
Then obviously at some point you need to release it.
try [accountID retain] before you release the array

NSArray filled with bool

I am trying to create an NSArray of bool values. How many I do this please?
NSArray *array = [[NSArray alloc] init];
array[0] = YES;
this does not work for me.
Thanks
NSArrays are not c-arrays. You cant access the values of an NSArray with array[foo];
But you can use c type arrays inside objective-C without problems.
The Objective-C approach would be:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[NSNumber numberWithBool:YES]];
//or
[array addObject:#(NO)];
...
BOOL b = [[array objectAtIndex:0] boolValue];
....
[array release];
EDIT: New versions of clang, the now standard compiler for objective-c, understand Object subscripting. When you use a new version of clang you will be able to use array[0] = #YES
Seems like you've confused c array with objc NSArray. NSArray is more like a list in Java, into which you can add objects, but not values like NSInteger, BOOL, double etc. If you wish to store such values in an NSArray, you first need to create a mutable array:
NSMutableArray* array = [[NSMutableArray alloc] init];
And then add proper object to it (in this case we'll use NSNumber to store your BOOL value):
[array addObject:[NSNumber numberWithBool:yourBoolValue]];
And that's pretty much it! If you wish to access the bool value, just call:
BOOL yourBoolValue = [[array objectAtIndex:0] boolValue];
Cheers,
Pawel
Use [NSNumber numberWithBool: YES] to get an object you can put in the collection.