How to add an object to array? - ios

I'm using an NSMutableArray to populate cells in my tableview. The problem is, when I try adding an object to my array, it replaces all the objects with the one that was added so I always only have 1 object in my array. Because of this, my tableview always has one cell that is just overwritten whenever the below method is called. Am I missing something?
_selectedThingArray = [[NSMutableArray alloc] init];
_currentThing = newThing;
//Note: newThing is the object being passed when this method is called.
//It is the new data that will should passed into the cell.
[_selectedThingArray addObject:_currentThing];
NSLog(#"%#", newThing);
NSLog(#"array: %#", _selectedThingArray);
[self.tableView reloadData];

Is this line:
_selectedThingArray = [[NSMutableArray alloc] init];
executed every time you "try adding an object"? If yes, then this is your problem. Instead of adding an object to an existing array, you replace it with a brand new array and add object to this new array.
You need to either create the array at some point before you “try adding an object”, or create the array in the same place you're doing it now, but only when you have not already created one.

Add this if condition before allocation:
if(!_selectedThingArray)
_selectedThingArray = [[NSMutableArray alloc] init];
Instead of this only:
_selectedThingArray = [[NSMutableArray alloc] init];
Everything will be fixed.

Related

NSMutableArray becomes immutable when reinstantiated?

I've made a NSMutableArray a property on my view controller, which holds some core data objects for users.
When the user presses a button , I clear out the contents of the mutable array with a while loop,
while (self.mArray.count != 0){
[context deleteObject:self.mArray[0]];
[self.mArray removeObjectAtIndex:0];
}
After the while loop, I reinit the array:
self.mArray = [[NSMutableArray alloc] init];
I know it isn't necessary since there should be zero objects left in the array, but regardless, when I reinitialize the array, and then check the class of the array in the debugger, I get __NSArrayI, which is corroborated by an exception thrown when I attempt to add an object into self.mArray right afterwards.
I've looked for any other references to my array, but I've always passed around [self.mArray mutableCopy] as arguments to other methods, and I never cast it as an NSArray. I just don't understand how calling [[NSMutableArray alloc] init] would initialize the array as an immutable array.
What am I missing?
It's likely that you have declared mArray as copy in the property declaration. Change that to strong.

I need an NSMutableDictionary, where the values will be arrays, that will be created while the app is running, and filled up later

So at runtime I initialize my NSMutableDictionary, and then when the user clicks on certain buttons, the app needs to get the name of this button and this name will be the key. Then he will click on another button, and this button's name will be put into an array, and the array will become the value of the first button name's key. However, later the user will keep doing this, and if he ends up clicking on a button that already is a value in the dictionary, then the second button he presses must be added to the array already associated with that key. Here is my code so far.
closestBeaconsDictionary is the main dictionary. closestBeaconName is a variable that makes up the keys, and pinNumberName is the value that must be put into an array. closestBeaconName and pinNumberName are constantly changing based on what buttons the user presses.
//first, check to see if the key already exists. If not, then add the key to
//closestBeaconsDictionary and then create an array and add this array to the dictionary
//and then add pinNumberName to this array.
if ([closestBeaconsDictionary objectForKey:pinNumberName] == nil)
{
NSMutableArray *closestPinsToBeacon = [[NSMutableArray alloc] init];
[closestPinsToBeacon addObject:pinNumberName];
[closestBeaconsDictionary setObject:closestPinsToBeacon forKey:closestBeaconName];
}
else
{
//what do I do here?? How do I access the dictionary that is at key:pinNumberName
//and then add an object to it?
}
So, my question is basically what do I put in the else statement? I'm confused because isn't closestPinsToBeacon basically destroyed after the block of code runs?
Try this:
if ([closestBeaconsDictionary objectForKey:pinNumberName] == nil)
{
NSMutableArray *closestPinsToBeacon = [[NSMutableArray alloc] init];
[closestPinsToBeacon addObject:pinNumberName];
[closestBeaconsDictionary setObject:closestPinsToBeacon forKey:closestBeaconName];
}
else
{
NSMutableArray *arr = [[NSMutableArray alloc] init];
arr = [[closestBeaconsDictionary objectForKey: closestBeaconName] mutableCopy];
[arr addObject:pinNumberName];
[closestBeaconsDictionary removeObjectForKey: closestBeaconName];
[closestBeaconsDictionary setObject:arr forKey: closestBeaconName];
}
Hope this helps.. :)

addObjectsFromArray will not add them as new objects

My problem is when I copy an array with objects, it seems that if i change the copied array, the original array changes as well. Below is a simplified version of my code.
I have an array of objects
#interface TimesViewController (){
NSMutableArray *route1;
}
I fill these objects up in my ViewDidLoad method
route1 = [[NSMutableArray alloc] init];
while (sqlite3_step(statement) == SQLITE_ROW) {
StopsOnRoutes *stopOnRoutes = [[StopsOnRoutes alloc] init];
[stopOnRoutes setStart_time:p_time];
[stopOnRoutes setStart_route_id:p_route];
[stopOnRoutes setStart_stop_id:p_stop];
[stopOnRoutes setStop_time:c_time];
[stopOnRoutes setStop_route_id:c_route];
[stopOnRoutes setStop_stop_id:c_stop];
[stopOnRoutes calc];
[route1 addObject:stopOnRoutes];
}
BUT when I try to copy route1 and make a few changes, they change both in route1 and amTimes
NSMutableArray *amTimes = [[NSMutableArray alloc] init];
[amTimes addObjectsFromArray:route1];
for(int i = 0; i<amTimes.count; i++){
[[amTimes objectAtIndex:i] setStop_time:[[amTimes objectAtIndex:i] stop_time]-86400];
[[amTimes objectAtIndex:i] setStart_time:[[amTimes objectAtIndex:i] start_time]-86400];
}
How can I copy route1 to amTimes, so if I change an object in AM times, it won't change in route1.
The way arrays work they simply hold references (pointers) to the objects in the array. Therefore when you add objects, it does not create a new object and point to it, it simply points to that very same object. What you want to do is referred to as a deep copy array, which involves coping each object inside the array.
Which is what happens when you use
- (instancetype)initWithArray:(NSArray *)array copyItems:(BOOL)flag
Each object in the array is send a copyWithZone, you can implement copyWithZone in each of the objects you want to add to your array, and then do
[myArray addObject[myObject copy]];
Or you can also use
[[NSArray alloc] initWithArray:otherArray copyItems:YES] //You need to implement copyWithZone in the items you want to copy.
This will give you the result that you want.
You need to have your StopOnRoutes class implement the NSCopying protocol and the copyWithZone: method. This method needs to create a copy of self.
Then you can do this:
NSMutableArray *amTimes = [[NSMutableArray alloc] init];
for (StopOnRoutes *obj in route1) {
[amTimes addObject:[obj copy]];
}
Container objects don't contain copies of the objects that are added to them, they contain pointers to the objects. If you add the same object to 2 arrays, it is a member of both arrays.
If you want to create an array of copies, you need to do several things:
You need to implement the NSCopying protocol for the objects in your array so you can copy them.
Then you'd need to create a new mutable array with room for the same number of elements as the first array, loop through the first array, copy each item, and add it to the second array.
If your array contains only standard system objects that support NSCopying then your work is simpler. If your array contains different kinds of custom objects or complex custom objects then you might have more work to do.
Try using setArray: i.e.[amTimes setArray:route1];

How to add strings to an NSMutableArray

I am trying to select multiple UITableViewCells, it is working fine, but I can't add strings to my NSMutableArray.
I am using this code, and my log always is (null):
self.mutarray = [[NSMutableArray alloc] init];
[self.mutarray addObject:path]; //path is an NSString
NSLog(#"%#", self.mutarray);
It must add the path of the UITableViewCell to the NSMutableArray, is that even possible?
Oh, and I am calling this in - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
As per your comments "it shows only the new added string, but not all strings.". This is because you are allocating NSMutable Array in the delegate method of table view. Everytime you hit the cell a new array is get allocated.
Either allocate your "mutarray" array in ViewDidLoad
Or
Only allocate it if it is nil or empty.
if(!self.mutarray)
self.mutarray = [[NSMutableArray alloc] init];
It seems that you haven't initialized your array. A good practice for properties is using something called lazy initialization.
Add this method.
- (NSMutableArray *)mutarray
{
if (!_mutarray) {
_mutarray = [[NSMutableArray alloc] init];
}
return _mutarray;
}
So every time you request the array, the accessor will make sure that the object is created before returning it. This is a good way of defensive programming.
You have to alloc/init before adding any objects:
if(!mutarray)mutarray = [[NSMutableArray alloc]init];
[self.mutarray addObject:path];
Have you tried to add a copy of the path?
Since UITableViewCells are resused, maybe the problem resides to this?
[self.mutarray addObject:[path copy]];

NSMutable Array won't alloc, remains nil

A XML parser is trying to alloc its delegate's NSMutable array called masterCodeList. From the following code, you'll see that this fails. (I am a total newbie.)
if (dataController.masterCodeList == nil){
dataController.masterCodeList =[[NSMutableArray alloc] init];
if (dataController.masterCodeList == nil) {
NSLog(#"the init of the mutable array did NOT work");
}
}
I get the the init of the mutable array did NOT work message every time. I am importing the dataController header.
#import "CodeDataController.h"
I am getting no other error message, the parser is parsing fine and the app is running smoothly without content.
Thanks in advance.
What does your declaration of masterCodeList look like?
Is it a property, and is it synthesized, or are you making your own setter/getter?
An alternative would be to try using an intermediate placeholder, ie:
NSMutableArray *temp = [[NSMutableArray alloc] init];
[dataController setMasterCodeList:temp];
and see if that sets your array correctly.
(note: that code may or may not have leaks)
could you post your implementation of the dataController object in this class, and its attributes from the other class?
you also may want to try using the isEqual method instead of == nil.

Resources