How to store enum values in a NSMutableArray - iphone

My problem is since an enum in objective-c essentially is an int value, I am not able to store it in a NSMutableArray. Apparently NSMutableArray won't take any c-data types like an int.
Is there any common way to achieve this ?
typedef enum
{
green,
blue,
red
} MyColors;
NSMutableArray *list = [[NSMutableArray alloc] initWithObjects:
green,
blue,
red,
nil];
//Get enum value back out
MyColors greenColor = [list objectAtIndex:0];

Wrap the enum value in an NSNumber before putting it in the array:
NSNumber *greenColor = [NSNumber numberWithInt:green];
NSNumber *redColor = [NSNumber numberWithInt:red];
NSNumber *blueColor = [NSNumber numberWithInt:blue];
NSMutableArray *list = [[NSMutableArray alloc] initWithObjects:
greenColor,
blueColor,
redColor,
nil];
And retrieve it like this:
MyColors theGreenColor = [[list objectAtIndex:0] intValue];

A modern answer might look like:
NSMutableArray *list =
[NSMutableArray arrayWithArray:#[#(green), #(red), #(blue)]];
and:
MyColors theGreenColor = ((NSInteger*)list[0]).intValue;

Macatomy's answer is correct. But instead of NSNumber I would suggest you use NSValue. That is its purpose in life.

NSMutableArray *corners = [[NSMutableArray alloc] initWithObjects:
#(Right),
#(Top),
#(Left),
#(Bottom), nil];
Corner cornerType = [corner[0] intValue];

You can wrap your enum values in a NSNumber object:
[NSNumber numberWithInt:green];

To go with NSNumber should be the right way normally. In some cases it can be useful to use them as NSString so in this case you could use this line of code:
[#(MyEnum) stringValue];

Related

Sorting two NSMutableArrays by 'nearest distance' first

I have two arrays, both full of NSString objects like this:
NSMutableArray *titles = [[NSMutableArray alloc] initWithObjects:#"Title1", #"Title2", #"Title3", #"Title4", #"Title5", nil];
NSMutableArray *distances = [[NSMutableArray alloc] initWithObjects:#"139.45", #"23.78", #"347.82", #"10.29", #"8.29", nil];
How can I sort both arrays by the nearest distance first?
So the results would be like this:
titles = #"Title5", #"Title4", #"Title2", #"Title1", #"Title3"
distances = #"8.29", #"10.29", #"23.78", #"139.45", #"347.82"
I understand that NSSortDescriptor can be used in these circumstances but after looking through the documentation, I am still unsure about how.
I would sort the distances this way...
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSArray *sortedDistances = [listItem sortedArrayUsingComparator: ^(id a, id b) {
NSNumber *aNum = [f numberFromString:a];
NSNumber *bNum = [f numberFromString:b];
return [aNum compare:bNum];
}];
I can't think of a particularly quick way to get the associated titles sorted, but this should work ...
NSMutableArray *sortedTitles = [NSMutableArray array];
NSDictionary *distanceTitle = [NSDictionary dictionaryWithObjects:titles forKeys:distances];
for (NSString *distance in sortedDistances) {
NSString *associatedTitle = [distanceTitle valueForKey:distance];
[sortedTitles addObject:associatedTitle];
}
You can use an NSComparator block and use NSArray's sortedArrayUsingComparator method. On that block, you will receive two objects to compare, and base on the comparison result, you can use NSMutableArray exchangeObjectAtIndex:withObjectAtIndex: method to change the values of titles.
Here is a sample how I sort an array of dictionaries by distance value:
-(void)reorderByDistance {
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:#"distance" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
self.contentArray = [self.contentArray sortedArrayUsingDescriptors:sortDescriptors];
}
And my dictionary looks like this:
NSDictionary *dict1 = [[NSDictionary alloc] initWithObjectsAndKeys:#"1", #"id", #"Business #1", #"name", #"This business does some pretty remarkable things", #"description", #"Alley Bar", #"category", #"1.2", #"distance", nil];
One approach would be to create a dictionary mapping titles to distances, sort the distances, and then iterate through the distances to recreate the titles:
NSMutableArray *titles = [[NSMutableArray alloc] initWithObjects:#"Title1", #"Title2", #"Title3", #"Title4", #"Title5", nil];
NSMutableArray *distances = [[NSMutableArray alloc] initWithObjects:#"139.45", #"23.78", #"347.82", #"10.29", #"8.29", nil];
//Create a map of current titles to distances
NSDictionary *titleDistanceMap = [NSDictionary dictionaryWithObjects:titles forKeys:distances];
//Need to sort the strings as numerical values
[distances sortUsingComparator:^(NSString *obj1, NSString *obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
//Now re-populate the titles array
[titles removeAllObjects];
for (NSString *distance in distances){
[titles addObject:[titleDistanceMap objectForKey:distance]];
}

Custom setter in objective c

I'm trying to declare a custom getter of a NSDictionary but I can't get it to work.
So far I have the #property declared and the synthesize syntax.
#property (nonatomic, strong) NSDictionary *variableDictionary;
#synthesize variableDictionary = _variableDictionary;
I want to declare a setter for the dictionary that gives it some standard values.
-(void)setVariableDictionary:(NSDictionary *)variableDictionary {
NSNumber *x = [NSNumber numberWithDouble:20];
NSNumber *a = [NSNumber numberWithDouble:10];
NSNumber *b = [NSNumber numberWithDouble:5];
NSDictionary *_variableDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
}
When I use the above method I get a warning unused variable, and if I remove the underscore from the NSDictionary variable definition, I get an error saying 'redefinition of variable dictionary'.
I'm not sure of the correct way to do this.
_variableDictionary is already declared.
Replace
NSDictionary *_variableDictionary = [[NSDictionary alloc]
initWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
with
_variableDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
In your custom setVarableDictionary: setter method, when you write:
NSDictionary *_variableDictionary = _variableDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
this declares and sets value for a new local variable within the scope of your function only. The warning message you get is because that variable is not used before it goes out of scope.
Instead of creating a local variable, you should just set the value of the ivar that underlies your property, like this:
_variableDictionary = [NSDictionary dictionaryWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
First off, the setter implementation doesn't really make any sense considering it will never change the value (it's only function is to initialize). Nonetheless (assuming this would change), if you want to test the value in your setter, you could make it look something like this
-(void)setVariableDictionary:(NSDictionary *)variableDictionary {
NSNumber *x = [NSNumber numberWithDouble:20];
NSNumber *a = [NSNumber numberWithDouble:10];
NSNumber *b = [NSNumber numberWithDouble:5];
_variableDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
NSLog(#"%#", _variableDictionary);
}
This will tell you whether or not the method is even being called. If it's not then you won't get the NSLog message.
This works on my end, if it's not on yours then there is something else going on.
If I understood your question. This might help
-(void)setVariableDictionary:(NSDictionary *)newVariableDictionary
{
if (variableDictionary != newVariableDictionary) {
variableDictionary = newVariableDictionary;
}
}
in your code.
-(void)setVariableDictionary:(NSDictionary *)variableDictionary {
its normal that it will give you an error when you redeclare your parameter. (NSDictionary *)variableDictionary
Try doing it this way, set your property as mentioned below:
#property (nonatomic, strong,setter = setTheVariableDictionary:) NSDictionary *variableDictionary;
Remove
-(void)setVariableDictionary:(NSDictionary *)variableDictionary
and write is as
-(void)setVariableDictionary:(NSDictionary *)thevariableDictionary
Hope this helps you.

Array in UITextView

I have an arrayappdeligate.biblearray. I just want to display this array in a textview. This array contains sql datas of 4 types chapterno, verses, genisis and text. i need to extract only the verses and display it in textview how to do this?
It seems biblearray has the objects of type bible. You can get the verses from bible objects like this,
bible *_bible = (bible *)[appDelegate.bibleArray objectAtIndex:0];
textView.text = [_bible verses];
or directly as,
textView.text = [[appDelegate.bibleArray objectAtIndex:0] verses];
If you want to display all the verses in the textView, you can do it like this,
NSArray *allVerses = [appDelegate.bibleArray valueForKey:#"verses"];
textView.text = [allVerses componentsJoinedByString:#"\n\n"];
#"\n\n" adds two new lines between the verses.
You need to do some alteration. Create NSDisctionary instead.
Take a dictionary where you are adding data from database
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
NSMutableArray *chapterno = [[NSMutableArray alloc]init];
NSMutableArray *verses = [[NSMutableArray alloc]init];
NSMutableArray *genisis = [[NSMutableArray alloc]init];
NSMutableArray *text = [[NSMutableArray alloc]init];
//Add data you are getting from database
[chapterno addObject:chapternodata];
[verses addObject:versesdata];
[genisis addObject:genisisdata];
[text addObject:textdata];
[dict setValue:chapterno forKey:#"chapterno"];
[dict setValue:verses forKey:#"verses"];
[dict setValue:genisis forKey:#"genisis"];
[dict setValue:text forKey:#"text"];
[chapterno release];
[verses release];
[genisis release];
[text release];
Take one NSDictionary in AppDelegate say appDict and make it equal to dict
NSMutableArray *arrVerses = [[objAppDel.appDict objectForKey:#"verses"];
txt.text = [arrVerses description];

How to add an integer to an array?

This must be quite basic, but I was wondering how to add an integer to an array?
I know I can add strings like this:
NSMutableArray *trArray = [[NSMutableArray alloc] init];
[trArray addObject:#"0"];
[trArray addObject:#"1"];
[trArray addObject:#"2"];
[trArray addObject:#"3"];
But I guess I can't simply add integers like so:
NSMutableArray *trArray = [[NSMutableArray alloc] init];
[trArray addObject:0];
[trArray addObject:1];
[trArray addObject:2];
[trArray addObject:3];
At least the compiler isn't happy with that and tells me that I'm doing a cast without having told it so.
Any explanations would be very much appreciated.
Yes that's right. The compiler won't accept your code like this. The difference is the following:
If you write #"a String", it's the same as if you created a string and autoreleased it. So you create an object by using #"a String".
But an array can only store objects (more precise: pointers to object). So you have to create objects which store your integer.
NSNumber *anumber = [NSNumber numberWithInteger:4];
[yourArray addObject:anumber];
To retrive the integer again, do it like this
NSNumber anumber = [yourArray objectAtIndex:6];
int yourInteger = [anumber intValue];
I hope my answer helps you to understand why it doesn't work. You can't cast an integer to a pointer. And that is the warning you get from Xcode.
EDIT:
It is now also possible to write the following
[yourArray addObject:#3];
which is a shortcut to create a NSNumber. The same syntax is available for arrays
#[#1, #2];
will give you an NSArray containing 2 NSNumber objects with the values 1 and 2.
You have to use NSNumbers I think, try adding these objects to your array: [NSNumber numberWithInteger:myInt];
NSMutableArray *trArray = [[NSMutableArray alloc] init];
NSNumber *yourNumber = [[NSNumber alloc] numberWithInt:5];
[trArray addObject: yourNumber];
You can also use this if you want to use strings:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:[NSString stringWithFormat:#"%d",1]];
[[array objectAtIndex:0] intValue];

NSMutableArray Exc_Bad_Access

I only have this code in m. file
NSMutableArray * arrayOfBools;
arrayOfBools=[[NSMutableArray alloc] initWithCapacity:1000];
NSNumber *ijk =(NSNumber*) 9;
[arrayOfBools addObject:ijk];
Get error o this [arrayOfBools addObject:ijk];
You can't declare and set an NSNumber like this: NSNumber *ijk =(NSNumber*) 9;.
This will set it to an integer (9).
Use this:
NSNumber *ijk = [NSNumber numberWithInt:9];
The third line, the declaration of the NSNumber is incorrect. if you are attempting to wrap a bool into a NSNumber, use NSNumber *test = [NSNumber numberWithBool:YES];