Getting out a undefined number of ViewController from an Array - iphone

In my app, I load UIViewController into an array from a .plist, and then, I need to get those VC's out. The problem is, since the number of VC's is not always the same, then I don't know how many I'm getting out each time. So I'm looking for a better engeneered solution - better iteration, rather than hard coding.
For example:
NSMutableArray *views = [[NSMutableArray alloc] init];
for (int i = [currentList count]; i > 0; i--) {
UIViewController *view = [[UIViewController alloc] init];
view.title = [NSString stringWithFormat:#"dgdg - %i", i];
[views addObject:view];
}
So there is my array of VC's, and now:
myIvar = [[CustomSubClass alloc] initWithViewControllers:**help** nil];
I tried:
myIvar = [[CustomSubClass alloc] initWithViewControllers:[views copy], nil];
and:
myIvar = [[CustomSubClass alloc] initWithViewControllers:[NSIndexSet..., nil];
I tried:
myIvar = [[CustomSubClass alloc] initWithViewControllers:[views objectAtIndex:0]... nil];
but none of it worked. Thanks in advance.

The syntax you want is like this:
[[CustomSubClass alloc] initWithViewControllers:[views objectAtIndex:0], [views objectAtIndex:1], [views objectAtIndex:2], nil];
Basically just repeat have all your arguments separated by commas, then always have the final argument be nil.

views is an array and you can pass this directly as a parameter like so:
 myIvar = [[CustomSubClass alloc] initWithViewControllers:views];

Related

Trying to find leak of type NSMutableArray. Instruments shows leak in method.

I eliminated all the leaks from my current app. However Instruments constantly tells me that I have a leak in the method shown below.
The leak is of type NSMutableArray and has a size of either 16 or 32 bytes. Yes, I know that's not much but it adds up. Also see it as an academic question that I need to solve to make my code leakless.
+ (id) meterFromDict:(NSDictionary*)dict {
Meter* resMeter = [[Meter alloc] initWithType:[[dict objectForKey:#"MeterBase"] intValue]];
//NSLog(#"dict: %#",dict);
resMeter.volume = nil;
resMeter.sounds = nil;
resMeter.repeats = nil;
resMeter.volume = [[[NSMutableArray alloc] initWithArray:[dict objectForKey:#"volumeArray"]] autorelease];
resMeter.sounds = [[[NSMutableArray alloc] initWithArray:[dict objectForKey:#"soundsArray"]] autorelease];
resMeter.repeats = [[[NSMutableArray alloc] initWithArray:[dict objectForKey:#"repeatsArray"]] autorelease];
//NSLog(#"MeterFromDict called and resmeter.repeats count is : %i",[resMeter.repeats count]);
resMeter.bpm = [[dict objectForKey:#"BPM"] floatValue];
return [resMeter autorelease];
}
Without looking at your Instruments output directly I can't tell exactly, but you're writing some redundant code: Try this:
+ (id) meterFromDict:(NSDictionary*)dict {
Meter* resMeter = [[Meter alloc] initWithType:[[dict objectForKey:#"MeterBase"] intValue]];
//NSLog(#"dict: %#",dict);
resMeter.volume = [dict objectForKey:#"volumeArray"];
resMeter.sounds = [dict objectForKey:#"soundsArray"];
resMeter.repeats = [dict objectForKey:#"repeatsArray"];
//NSLog(#"MeterFromDict called and resmeter.repeats count is : %i",[resMeter.repeats count]);
resMeter.bpm = [[dict objectForKey:#"BPM"] floatValue];
return [resMeter autorelease];
}
There's no point in nilling your properties before assigning new values to them.
Also, No point creating new arrays for arrays that you already have. And if you have properly declared your volume, sounds and repeats properties with copy instead of retain.
Try that and see if it works better.

Initialize 2 dim array NSMutableArray

For C I would init an array like this:
NSInteger x[3][10]; That works.
Below I have a one dim array that works. Would like to move all of this to a 2 dim array, How do I init it? So in other words take the code below and make it work with 2 dimensions.
NSMutableArray *SRData;
SRData = [[NSMutableArray alloc] init];
NSMutableDictionary *SRRow;
SRRow = [[NSMutableDictionary alloc] init];
[SRRow setObject:#"Read" forKey:#"Descr"];
[SRRow setObject:#"Read2.png" forKey:#"Img"];
[SRRow setObject:#"Read the codes" forKey:#"Det"];
[SRData addObject:SRRow] ;
[SRRow release];
In Objective-C, you just have to have an array of arrays to get the second dimension. To my knowledge, there is no shorthand, so you're stuck doing something like the following:
NSMutableArray *firstDimension = [[NSMutableArray alloc] init];
for (int i = 0; i < rows; i++)
{
NSMutableArray *secondDimension = [[NSMutableArray alloc] init];
[firstDimension addObject:secondDimension];
}
So all you would do is add your other objects (in your case, the NSMutableDictionarys) to the secondDimension array. Usage would be like:
[[firstDimension objectAtIndex:0] objectAtIndex:0];
Edit
Full code example:
NSMutableArray *SRData = [[NSMutableArray alloc] init]; //first dimension
NSMutableArray *SRRow = [[NSMutableArray alloc] init]; //second dimension
[SRData addObject:SRRow]; //add row to data
[SRRow release];
NSMutableDictionary *SRField = [[NSMutableDictionary alloc] init]; //an element of the second dimension
[SRField setObject:#"Read" forKey:#"Descr"];
//Set the rest of your objects
[SRRow addObject:SRField]; //Add field to second dimension
[SRField release];
Now, to get at that "field" you would use code such as the following:
[[SRData objectAtIndex:0] objectAtIndex:0]; //Get the first element in the first array (the second dimension)

Passing NSMutableArray from delegate

I'm doing an Iphone aplication and in the delegate class i call a method from another class which return a NSMutableArray filled with the information i need:
NSMutableArray *array = [[NSMutableArray initWithObjects:nil] retain];
array = [xml loadXML:#"info.xml"];
Now I want to pass this array into the viewController class so i can do things with my mutable array. I do the following:
...
[self.window addSubview:viewController.view];
[self.viewController loadLocations:array];
[self.window makeKeyAndVisible];
In delegate, the array is ok, it has the data i want, however, in the viewController class (which is a UIViewController) the array is messed up.
-(void)loadLocations:(NSMutableArray*)_array{
NSLog(#"%f", [[_array objectAtIndex:0] lat]); // This sould be 42.000 but it is 0.00000 and all of the other indexes
You're in trouble right from the beginning:
NSMutableArray *array = [[array initWithObjects:nil] retain];
You're calling "initWithObjects" on "array", but you haven't allocated "array" yet.
You want something like:
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:nil];
or just :
NSMutableArray *array = [[NSMutableArray alloc] init];
This part is invalid:
NSMutableArray *array = [[array initWithObjects:nil] retain];
array = [xml loadXML:#"info.xml"];
The first line is not used because the second line is setting the array pointer to the result of [xml loadXML:]
I think this should suffice:
NSMutableArray *array = [[NSMutableArray alloc] initWithArray:[xml loadXML:#"info.xml"]];

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).

Table crashes when sorting the data multiple times

I have a tableview with a navigationBar with a segmentedControl on the top of the view. I have set up the segmentedControl with buttons that sort the table by either "FirstName" or "LastName". It works perfectly the first 2-4 of times you press the sorting buttons, but then the app crashes.
The debugger and console seem to be of no help finding the source of the bug. Does anyone see any glaring mistakes in my code?
Here is my code below, let me know if you have any questions. Thanks!
- (IBAction)sortingSegmentAction:(id)sender{
NSString *keyToSortBy = [NSString alloc];
if([sender selectedSegmentIndex] == 0)
{
self.sortingSegmentActionPressed = 0;
keyToSortBy = #"FirstName";
}
else if([sender selectedSegmentIndex] == 1)
{
self.sortingSegmentActionPressed = 1;
keyToSortBy = #"LastName";
}
//Create the sort descriptors
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:keyToSortBy ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
//Sort allSubItams by the values set in the sort descriptors
NSArray *sortedArray;
self.sortedArray = [allSubItems sortedArrayUsingDescriptors:sortDescriptors];
//Recreate the data structure by putting the newly sorted items into a dictionary sorted by inital letters.
NSDictionary *eachItemList; //A DICTIONARY FOR PUTTING ALL THE DATA FOR EACH ITEM IN IT'S OWN SECTION
NSMutableDictionary *tempSectionedDictionaryByFirstLetter = [[NSMutableDictionary alloc] init];
for (eachItemList in sortedArray) //eachElementList is a dictionary with a section for each item
{
NSDictionary *aDictionary = [[NSDictionary alloc] initWithDictionary:eachItemList];
NSString *firstLetterString;
firstLetterString = [[aDictionary valueForKey:keyToSortBy]substringToIndex:1];
NSMutableArray *existingArray;
if (existingArray = [tempSectionedDictionaryByFirstLetter valueForKey:firstLetterString])
{
[existingArray addObject:eachItemList];
} else {
NSMutableArray *tempArray = [NSMutableArray array];
[tempSectionedDictionaryByFirstLetter setObject:tempArray forKey:firstLetterString];
[tempArray addObject:eachItemList];
}
[aDictionary release];
[eachItemList release];
}
//Set the data source for the table (sectionedDictionaryByFirstLetter) to tempSectionedDictionaryByFirstLetter.
self.sectionedDictionaryByFirstLetter = tempSectionedDictionaryByFirstLetter;
NSMutableArray *keyArray = [[NSMutableArray alloc] init];
[keyArray addObjectsFromArray:[[self.sectionedDictionaryByFirstLetter allKeys] sortedArrayUsingSelector:#selector(compare:)]];
self.keys = keyArray;
[self.tableView reloadData];
[keyArray release];
[tempSectionedDictionaryByFirstLetter release];
}
Don't release eachItemList at the end of your loop. You did not explicitly allocate it in this context so you shouldn't release it.
The for (object in array) loop gives you a reference to the object in the array, not a copy. By sending a release message to this reference, you are decrementing the retain count of this object while it is still in the array. After a few times (depending on how many times the object has been retained, NSArray for example retains objects when they are added to the array) it's retain count will reach 0, and it will then become deallocated and you'll get crashes regarding unrecognised selectors or EXC_BAD_ACCESS and possibly other kinds of errors.