How to deal with booleans in NSMutableArrays? - objective-c

Can someone tell me why my application crashes here ?
and why it does not crash when i replace the YES objects with NSString values ?
all i want to do is to store boolean data into array and to modify these data later,
can someone please tell me how to do this ?
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray* arr = [[NSMutableArray alloc] initWithObjects:YES, YES, YES, YES, nil];
NSLog([arr objectAtIndex:1]);
}

YES and NO are BOOLs, which is not an Objective-C class. Foundation containers can only store Objective-C objects.
You need to wrap them in an NSNumber, like:
NSNumber* yesObj = [NSNumber numberWithBool:YES];
NSMutableArray* arr = [[NSMutableArray alloc] initWithObjects:
yesObj, yesObj, yesObj, yesObj, nil];
NSLog(#"%d", [[arr objectAtIndex:1] boolValue]);
The reason why it accepts NSString is because an NSString is a kind of Objective-C class.

Related

How to produce 2 dimensional Array in Objective C

How do i produce a 2 dimensional NSMutable array as this:
Array:
=>[item1]=>[item1a,item1b,item1c...]
=>[item2]=>[item2a,item2b,item2c...]
...
=>[item10]=>[item10a,item10b,item10c...]
So far i've only been successful up to the [item1]=>[item1a,item1b,item1c...]
When i try to add more 2 dimensional array it keeps overriding the first row.
Create NSMutableArray and assign NSMutableArrays to it as its objects.
For example:
NSMutableArray * myBig2dArray = [[NSMutableArray alloc] init];
// first internal array
NSMutableArray * internalElement = [[[NSMutableArray alloc] init] autorelease];
[internalElement addObject:#"First - First"];
[internalElement addObject:#"First - Second"];
[myBig2dArray addObject:internalElement];
// second internal array
internalElement = [[[NSMutableArray alloc] init] autorelease];
[internalElement addObject:#"Second - First"];
[internalElement addObject:#"Second - Second"];
[myBig2dArray addObject:internalElement];
To make a 2 dimensional array you would make an array of arrays.
NSArray *2darray = [NSArray arrayWithObjects: [NSArray arrayWithObjects: #"one", #"two", nil], NSArray arrayWithObjects: #"one_2", #"two_2", nil]];
It gets very verbose but that is the way I know how to do this. An array of dictionaries may be better for your situation depending on what you need.
I wrote an NSMutableArray wrapper for easy use as a Two Dimensional array. It is available on github as CRL2DArray here . https://github.com/tGilani/CRL2DArray
First you to have set An NSMutableDictionary on .h file
#interface MSRCommonLogic : NSObject
{
NSMutableDictionary *twoDimensionArray;
}
then have to use following functions in .m file
- (void)setValuesToArray :(int)rows cols:(int) col value:(id)value
{
if(!twoDimensionArray)
{
twoDimensionArray =[[NSMutableDictionary alloc]init];
}
NSString *strKey=[NSString stringWithFormat:#"%dVs%d",rows,col];
[twoDimensionArray setObject:value forKey:strKey];
}
- (id)getValueFromArray :(int)rows cols:(int) col
{
NSString *strKey=[NSString stringWithFormat:#"%dVs%d",rows,col];
return [twoDimensionArray valueForKey:strKey];
}

Replace content of NSMutableArray with NSArray

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

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];

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.