How to insert object already existing objects in NSMutableArray list - objective-c

I am getting a problem, while inserting an object into the main List.
[editContactList addObject:editcontacts];
[editObject.contactList insertObject:editContactList atIndex:0];//error as mutating method sent to immutable object
[editcontacts release];

If you get that particular error, you don't actually have an NSMutableArray; you have an NSArray. Which is immutable. (Note that simply casting an NSArray to NSMutableArray does nothing, the array itself needs to be an instance of a mutable array, rarely seen with instance variables, especially those made accessible publicly.)
Edit: We're going to need some more information; how are these variables defined, how are they initialized, etc.

Related

NSMutableDictionary and mutableCopy

I'm confused by the code, below. Before I added the mutableCopy line, it didn't work. After I added the line, it did.
Why isn't aDict mutable to begin with? I declared aDict as an NSMutableDictionary.
- (void) myRoutine: (NSMutableDictionary *) dictOfDicts
{
NSMutableDictionary * aDict = dictOfDicts[dictOfDictsKey];
int data = [aDict[aDictKey] intValue];
aDict = [aDict mutableCopy];
aDict[aDictKey] = #(++data);
}
The declaration of dictOfDicts says it's a pointer to a mutable dictionary. However, it does not use Objective-C generics syntax to say what the types of the keys or values are. So, the most we (and the compiler) can assume is that the keys are id<NSCopying> and the values are id, completely generic object pointers.
You then initialize your aDict variable with a value obtained from dictOfDicts. You've declared that aDict is also a pointer to a mutable dictionary. That's its "static type", but the real type of the object it points to is determined at runtime by whatever object is held in dictOfDicts under that key. It might be a mutable dictionary or it might be something else. It compiles just find because the compiler can't know what type of object that value is.
However, the real type (a.k.a. "dynamic type") of the object governs what operations succeed or fail/crash/whatever. In your case, it sounds like it's an immutable dictionary. So, when you attempt to mutate it, "it didn't work" (you don't specify what actually happened).
You make a mutable copy and you're allowed to mutate that. However, that's now a separate object that the one in dictOfDicts. So, you're not modifying what you think you are.
The solution is to put mutable dictionaries into dictOfDicts in the first place. Or, even better, put objects of a custom class of your own design into it, and operate on real properties.

NSOrderedSet for object pointers only

I need to store a bunch of objects in an NSOrderedSet object.
Unfortunately, I don't want the set to perform any sort of equality checking on anything other than the object pointer itself.
It appears as though some objects (such as NSNumber) override isEqual: and perform internal value comparison, which means that two NSNumber instances with the same value (but different object pointers) cannot be stored in the same ordered set.
How can I work around this issue?
It has occurred to me that I could just store the object pointer itself as an NSValue or NSString object (using #"%p") instead.
However this means that I need to wrap all calls to containsObject: and indexOfObject: and create a new NSValue or NSString object every time I want to query the set.
Is there any better way of handling this?

Creating a NSMutableArray to hold pointers

I am trying to create a mutable array in objetive c to hold references to objects. The objects in the array are regularly updated through user interaction and i want the array to automatically reflect changes made to the objects as they occur. Does anyone know if there is a way to do this? Perhaps store pointers to the objects instead of the objects themselves in the array? Any help would be much appreciated
Thanks in advance
Edit: I should mention that the objects are not exactly being updated in the strict sense of the word. They are being reinitialized. For ex if i had a controller:
MyController = [MyController alloc] initWith.....]]
the above call is made again with different init parameters.
The array always stores the pointers.... It holds a strong reference to it or sends it a retain message (if using non ARC).
So
[myMutableArray addObject: anObject];
adds the pointer to it.
If you now change anObject's properties and access it later through the array, it will
give you the pointer to just that object with the changes to its properties.
Edit:
No, if you alloc/init, you are creating a new object instance and allocate new memory for it on the heap (ie, it's another pointer to a new memory address).
What exactly are you trying to accomplish? There sure is a way, if you provide a little more detail.
If you alloc/init the object with the same class, why not just create a method to change the object's properties:
Instead of
myObject = [[MyClass alloc] initWithParameter1: one parameter2: two];
You could create a method that changes these properties:
[myObject updateParameter1: anotherOne parameterTwo: anotherTwo];
And, of course, the advantage of a mutable array is, that you can change its contents, so like #Eli Gregory pointed out, you can replace an object with another one (or rather the pointers to it).
Because you want to point to a newly allocated and initialized object, you can't 'update' the pointer, what you can do is 'replace' the pointer with a new one at a certain index.
A method you could use to do this is:
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject
so it would look something like:
NewViewController *new = [[NewViewController alloc] init..];
[myArray replaceObjectAtIndex:x withObject:new];

Re-initialize NSMutableArray as NSMutableArray

I was having a problem with my app throwing an exception when calling removeObjectAtIndex on an NSMutableArray, saying that myLocationsArray was declared immutable. All other manipulation on that array was fine, it was most definitely declared correctly etc etc but somewhere in my app it was getting set as immutable. After investigating for a while trying to find where it was getting set immutable, I decided screw it and just redeclared the variable as such:
myLocationsArray = [[NSMutableArray alloc] initWithArray:[defaults
objectForKey:MYLOCATIONSARRAY_KEY]];
right before the removeObjectAtIndex call.
However I know this has got to be badwrong, I'm calling alloc/init twice on the same variable. However it's the only thing that has worked. Is there any way to remind this variable that it is an NSMutableArray without introducing memory leaks like I am?
NSUserDefaults returns immutable copy of your array. It doesn't matter whether you put NSArray or NSMutableArray in it, it always give you immutable copy back.
So, do this to get a mutable copy that you can work with
myLocationsArray = [[NSMutableArray alloc] initWithArray:[[[defaults objectForKey:MYLOCATIONSARRAY_KEY] mutableCopy] autorelease]];
or just this
myLocationsArray = [[defaults objectForKey:MYLOCATIONSARRAY_KEY] mutableCopy];
I would suggest to set a breakpoint on the line where your program is throwing an exception (the one containing removeObjectAtIndex) and inspect with the debugger the real type of the array. If you go with you mouse over the array name, a popup menu will display giving you all the information you need about the pointed object.
What I expect is that you find out this way that the object is an NSArray (vs. NSMutableArray) and then trace back to the point where you initialized it in the first place.
It looks like you're working with NSUserDefaults. All objects you get out of NSUserDefaults are always immutable, regardless of what you stored into it. NSUserDefaults doesn't keep a reference to the specific object you set into it, it keeps the data. It's effectively making a copy. When you get something out of NSUserDefaults, it makes a new (immutable) object from the data it has stored and gives that to you.
Unsurprisingly, you can't change what's stored in NSUserDefaults by mutating what you (think you) stored in it. You can only change what's stored by replacing what you previously stored by storing something anew.
The declaration should not matter; your error is a run-time error. It sounds like your myLocationsArray variable has been assigned an immutable array (NSArray) though whether it is being re-assigned somewhere or was always immutable is impossible to say from your code fragment.

Instance pointers in an array

I'm trying to save pointers of class instances into a mutable array. I'm able to do this but getting them back into use seems to be a problem. The next is how I inserted the pointers into the array:
Class *class = [Class new];
/* Do something with the instance */
[instanceArray addObject:class];
I am able to retrieve the wanted index from the array but when I try to access the instance variables etc. I only get compiler shouting at me or sometimes I get every variable as zero.
How am I supposed to get the instance back to use from the array? I know they are pointers but playing with them didn't seem to work.
Using addObject: the element is inserted at the end of the array. To retrieve it you can use -[NSArray objectAtIndex:]
Pointer arithmetic works in C since then your array is just a pointer to the first index, and array[i] is the same as *(array + i). In Objective-C this may still be done, however you're using an NSArray object. Now you don't have a pointer to the first object anymore, but to the instance of the class. To retrieve the objects stored in the array, you'll have to call the corresponding methods.
EDIT
So you are able to retrieve it from the array and then your pointer is not nil, so you do have access to the object. You know in Objective-C, all instance variables are private so you can't access them from outside. You'd have to declare them as properties first (please refer to the documentation). Also, when you declare a variable to be of type id, accessing a property with dot-syntax doesn't work, it will cause a compiler error.