How to add an integer to an array? - iphone

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

Related

Objective-C and ARC: Why value stored to during its initialization is never read?

I'm using this code with ARC:
NSMutableDictionary *datesDict = [[NSMutableDictionary alloc]init];
NSMutableArray *datesArray = [[NSMutableArray alloc]init];
for (NSString *key in programsArray) {
datesArray = [_onDemandDictionary objectForKey:key];
NSMutableArray *newDates = [[NSMutableArray alloc]init];
int count;
for (count = 0; count <datesArray.count; count++) {
NSMutableDictionary *programsDict = [[NSMutableDictionary alloc]init];
programsDict = [datesArray objectAtIndex:count];
[newDates addObject:[programsDict objectForKey:#"date"]];
}
[datesDict setObject:newDates forKey:key];
}
But when I run the analyzer tool I'm getting value stored to (datesArray and programsDict) during its initialization is never read on lines:
NSMutableArray *datesArray = [[NSMutableArray alloc]init];
programsDict = [datesArray objectAtIndex:count];
Why is this happening how do I get hid of the warning?
Thank you!
The issue is you create a new NSMutableArray and assign it to datesArray at the beginning
NSMutableArray *datesArray = [[NSMutableArray alloc]init];
Then almost immediately after you assign a completely different value to datesArray with
datesArray = [_onDemandDictionary objectForKey:key];
I would just start with
NSMutableArray *datesArray = nil;
It's the same concept for programsDict.
On line 2, you create a new array datesArray.
Then, on line 6 (first line of the for loop), you set a new value to datesArray.
The compiler is just warning you that the line 2 has no effect, and that the code is bugged (in the sense it does not do what you expect).
True, the programsArray could be an empty array, and in this case you want datesArray to just be initialized to use it after the snippet you showed us, but it would be better to make this explicit.
For programsDict, it is even easier: you initialize it with ... alloc] init] then set it to an object of datesArray, making the first operation useless.
You are not using datesArray in your loop, you are simply assigning it values, So either take it nil array like
NSMutableArray* datesArray = nil;
or like
NSMutableArray *datesArray;
to remove waring .

Add an array value to another array

How can I add an array value to another array?
I get the array using:
NSMutableArray *pointsArray = [[result componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] retain];
I want to add the first and the last value of pointsArray to another array.
[array addObject:[pointsArray objectAtIndex:0]]; //First Object
[array addObject:[pointsArray lastObject]]; //Last Object
But this array should be an NSMutableArray.
Get the value of array using objectAtIndex: method of NSArray.
as follows
NSUInteger totObjects = [pointsArray count];
[yourOtherArray addObject:[pointsArray objectAtIndex:0]]; //First Object
[yourOtherArray addObject:[pointsArray objectAtIndex:totObjects-1]]; //Last Object
Its simple just add like this
NSArray *otherArray = [[NSArray alloc] initWithObjects: [pointsArray objectAtIndex:0], [pointsArray objectAtIndex:[pointsArray count]-1],nil];
This can be achieved by using this:
NSMutableArray *recentPhotos = [[NSMutableArray alloc] init];
//add one object to the array
[recentPhotos addObject: selectPhotos];

problem while getting arrays from one class to another class

i am have 4 arrays in myclass.m
i need to get those arrays into myclassviewcontroller.m
for that i write code in myclassviewcontroller.m like this.
- (void)resultarrays :(NSMutableArray *)Agentids loanofficerid:(NSMutableArray *)Loanofficerid agentname:(NSMutableArray *)agentname agentemail:(NSMutableArray *)agentemail agentphone:(NSMutableArray *)Agentphone {
agentids = [[NSMutableArray alloc] initWithObjects:Agentids,nil];
loanofficerid = [[NSMutableArray alloc] initWithObjects:Loanofficerid,nil];
agentnames = [[NSMutableArray alloc] initWithObjects:agentname,nil];
agentemails = [[NSMutableArray alloc] initWithObjects:agentemail,nil];
agentphone = [[NSMutableArray alloc] initWithObjects:Agentphone,nil];
NSLog(#"123 %#",agentids);
NSLog(#"123 %#",loanofficerid);
NSLog(#"123 %#",agentnames);
NSLog(#"123 %#",agentphone);
}
in myclass.m i write this
myclassviewcontroller *LOVobj = [[myclassviewcontroller alloc]init];
[LOVobj resultarrays:resultData_agent loanofficerid:array1 agentname:array2 agentemail:array3 agentphone:array4];
then it displays all the objects that i print in console.
After this, In the button click i print these arrays then it prints null.
even i assign setter and getter methods to it.
i did n't what's the problem can any one please help me.
Thank u in advance.
First of all, change the code to this:
- (void)resultarrays :(NSArray *)Agentids loanofficerid:(NSArray *)Loanofficerid agentname:(NSArray *)agentname agentemail:(NSArray *)agentemail agentphone:(NSArray *)Agentphone {
agentids = [[NSMutableArray alloc] initWithArray: Agentids];
loanofficerid = [[NSMutableArray alloc] initWithArray: Loanofficerid];
agentnames = [[NSMutableArray alloc] initWithArray: agentname];
agentemails = [[NSMutableArray alloc] initWithArray: agentemail];
agentphone = [[NSMutableArray alloc] initWithArray: Agentphone];
NSLog(#"123 %#",agentids);
NSLog(#"123 %#",loanofficerid);
NSLog(#"123 %#",agentnames);
NSLog(#"123 %#",agentphone);
}
Don't pass mutable array if you don't want it to change.
First of all, you're creating arrays containing references to arrays, not arrays of the objects in the parameter arrays. And since you're storing the references of the parameter arrays, if the contents of the parameter arrays changes, so will all the references.
You probably instead want something like this for each array:
agentids = [NSMutableArray arrayWithArray: Agentids];
(and [agentids retain] since arrayWithArray returns an auto-released object).

How to store enum values in a NSMutableArray

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

Leaking Memory on iPhone :(

I'm a beginner at C, Obj-C and the iPhone, and I'm trying getting to grips with a lot of terminology used. I hope one of ye can help with a problem I have been struggling with for a few days now.
My code below is a method which call up a nib containing a search field and a table. The table is populated from a search of the array created for 'theList' below. Using 'Instruments', I am getting a Leak at the line:
NSDictionary *theItem = [NSDictionary dictionaryWithObjectsAndKeys:clientName,#"Name",clientId,#"Id",nil]; , but I can't figure out why :(
I know it's probably a difficult question to answer, but if any one can be of any help!
- (void)editClient:(id)sender {
if (pickList == nil) {
pickList = [[PickFromListViewController alloc] initWithNibName:#"PickList" bundle:nil];
}
TimeLogAppDelegate *appDelegate = (TimeLogAppDelegate *)[[UIApplication sharedApplication] delegate];
NSMutableArray *theList = [[NSMutableArray alloc] init];
int i;
for (i=0;i < [appDelegate.clients count];i++) {
Client *thisClient = [appDelegate.clients objectAtIndex:i];
NSString *clientName = [[NSString alloc] initWithString: thisClient.clientsName];
NSNumber *clientId = [[NSNumber alloc] init];
clientId = [NSNumber numberWithInt:thisClient.clientsId];
NSDictionary *theItem = [NSDictionary dictionaryWithObjectsAndKeys:clientName,#"Name",clientId,#"Id",nil];
[theList addObject:theItem];
theItem = nil;
[clientName release];
[clientId release];
}
[pickList createSearchItems:theList :NSLocalizedString(#"Client",nil)];
[theList release];
appDelegate.returningID = [NSNumber numberWithInt: projectsClientsId];
[self.navigationController pushViewController:pickList animated:YES];
}
Thanks in advance!
This returns allocated NSNumber instance.
NSNumber *clientId = [[NSNumber alloc] init];
This line overwrites the above clientId with another instance of NSNumber, numberWithInt returns autoreleased object, since you haven't allocated memory for it you should not call release, it will be released automatically.
clientId = [NSNumber numberWithInt:thisClient.clientsId];
You are calling release on clientId so you get memory problem.
To fix it remove the first line above which is useless in this case and update the second one to:
NSNumber * clientId = [NSNumber numberWithInt:thisClient.clientsId];
Then remove the:
[clientId release]
Because the clientId will be released automatically.
EDIT: Re still have problems ...
I'm not sure how to you manipulate the clients in app delegate, otherwise the code should work ok, I created small example, omitting the parts that I can't see (app delegate and clients):
// command line utility - foundation tool project:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSMutableArray * theList = [[NSMutableArray alloc] init];
int i = 0;
for (i = 0; i < 10; ++i)
{
NSString * clientName = [NSString stringWithString:#"client"]; //no need to release
NSNumber * clientId = [NSNumber numberWithInt:i];
NSDictionary * theItem = [NSDictionary dictionaryWithObjectsAndKeys:
clientName, #"name",
clientId, #"id",
nil];
[theList addObject:theItem];
}
for (id item in theList) for (id key in item) NSLog(#"%# - %#", key, [item objectForKey:key]);
[theList release];
[pool drain];
return 0;
}
You are creating clientID with [[NSNumber alloc] init], and then immediately overwriting it with an autoreleased NSNumber instance [NSNumber numberWithInt], and then you are releasing it later in your code, which you shouldn't do. Get rid of the [[NSNumber alloc] init] line and the [clientId release] line and that should fix it up a little.
Aside from the obvious leak of the NSNumber, there are a few other things I'd fix that may help. Most are fairly minor, but in my experience with Objective-C, less code == clearer code, something that is not equally true for languages like Bash or Perl. ;-)
- (void) editClient:(id)sender {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (pickList == nil) {
pickList = [[PickFromListViewController alloc] initWithNibName:#"PickList" bundle:nil];
}
TimeLogAppDelegate *appDelegate = (TimeLogAppDelegate*)[[UIApplication sharedApplication] delegate];
NSMutableArray *searchItems = [NSMutableArray array];
NSMutableDictionary *itemDict = [NSMutableDictionary dictionary];
for (Client *client in appDelegate.clients) {
[itemDict setObject:[client.clientsName copy] forKey:#"Name"];
[itemDict setObject:[NSNumber numberWithInt:client.clientsId] forKey:#"Id"];
[searchItems addObject:[[itemDict copy] autorelease]];
}
[pickList createSearchItems:searchItems :NSLocalizedString(#"Client",nil)];
[self.navigationController pushViewController:pickList animated:YES];
appDelegate.returningID = [NSNumber numberWithInt: projectsClientsId];
[pool drain];
}
There are a few mysterious points that make me suspicious:
The line just after the for loop tells pickList to do something with the NSMutableArray. That method should retain the new array, as well as release the old array if one exists. If you just overwrite the pointer, the old array will be leaked. (Also, this method is poorly named. Anonymous arguments (a colon with no preceding text) are legal in Objective-C, but considered extremely bad practice. Consider renaming the method to better express what it does.)
The next line seems to associate the pick list with a navigation controller. If it is custom code, make sure the -pushViewController:animated: method properly releases an existing pick list when a new one is specified.
Assigning to appDelegate.returningID is assumed to call the setter for a returningID property. Be sure that property retains or copies the NSNumber as necessary.
Memory leaks can be tricky to track down, even in Instruments, and you'll often find that it looks like Foundation classes (such as NSDictionary) are leaking like a sieve, but I have always been able to trace it back to an abnormality in my code. :-)