Assigning object pointers - objective-c

Is this pointer assignment correct?
customclass.somearray = &*otherarray;
where somearray and otherarray are NSArray objects.
If not, how do I solve my problem:
I want to share this otherarray object with customclass.somearray. And I want all changes
made to customclass.somearray to be made to the original otherarray too.
Doing it this way, it works. I just want to ask, is it correct?

Your two variables are pointers of the same type, so just assign one to the other:
customclass.somearray = otherarray;
The way you have written this is unnecessary. Using the dereference operator * essentially gives you the "contents" of the pointer. The address-of operator & correspondingly gives you the address of whatever you apply it to. Your pointer otherarray contains an address. If you dereference that address and then take the address of that, you end up right back where you started.
Be aware that the left side of this assignment is a property access (assuming that customclass is also an object and not just a struct). This means that the compiler will change your expression into:
[customclass setSomearray:&*otherarray];
// And my version will be changed into:
[customclass setSomearray:otherarray];
That is, it becomes a method call rather than a simple assignment. This does not affect the syntax you should use, however.

When working in Objective-C, you never deal with objects directly, but always refer to them via pointers. Always. In C++, you can declare an actual object on the stack, for example, but you never do that in Objective-C. So, if you have:
NSArray *otherArray = [NSArray arrayWithObjects:#"foo", #"bar", nil];
then otherArray is a pointer to an instance of NSArray. Likewise, your somearray property will be of type NSArray*, so the types will match and you can just assign one to the other:
customclass.somearray = otherarray;
Hope that helps.

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.

NSDictionary + ARC + copy vs reference

These are probably are pretty simple YES|NO type questions.
I have some NSDictionaries containing other NSDictionaries. Let's say NSDictionary_A and NSDictionary_B. These persist for the life of the app.
The NSDictionaries contained in NSDictionary_A are passed by reference to various objects:
track.instrument = [NSDictionary_A objectForKey:#"Blue"];
Later it gets changed:
track.instrument = [NSDictionary_A objectForKey:#"Red"];
So first question: The #property instrument is synthesized + retained as strong so does the setter for instrumentset the current value of instrument to nil before setting the new value, and if so, does this affect the source of the reference in NSDictionary_A - in other words, set the reference to nil'? Sounds wrong just writing it out.. so I think the answer is NO here. Also, it probably doesn't matter that the #property instrument is stored as weak or strong since the reference in NSDictionary_A1 persists for the app life but since it is a pointer, should be weak - YES?
Second question: An NSDictionary in NSDictionary_B is passed to an object but it can change some of the values in that NSDictionary:
track.playbackType = [NSDictionary_B objectForKey:#"Random"];
[track.playbackType objectForKey:#"maxRange"] = 20;
So should I be making a copy of the NSDictionary here because it's values will be changed or am I completely misunderstanding this whole reference passing thang?
You are getting mixed up in how pointers work.
For the first question, "track.instrument" is just a pointer. So it will start as "pointing to nil".
this:
track.instrument = [NSDictionary_A objectForKey:#"Blue"];
means, "stop pointing to nil and point to that object"
If you can ensure your dictionary will persist for the entire app then it doesnt matter, whatever is at #blue key will never get dealocated. But for the sake of having the correct code, it should be weak.
Edit: Had read the second question incorrectly.
Second question:
about this:
track.playbackType = [NSDictionary_B objectForKey:#"Random"];
first your pointer points to the NSDictionary from the dictionary.
[track.playbackType objectForKey:#"maxRange"] = 20;
Since it is a NSDictionary this is not valid. You cannot change NSDictionaries because they are immutable, it SHOULD be NSMutableDictionary.
HOWEVER if you are not interested in putting back the modified version into the original dictionary then you can copy it but as a NSMutableDictionary first, and then change it.
NSMutableDictionary *mutableDict = [[NSDictionary_B objectForKey:#"Random"] mutableCopy];
track.playbackType = mutableDict; //Note how track.playbackType has to be NSMutableDictionary aswell.
VERY IMPORTANT: Since you are creating a "new" dictionary. track.playbackType has to be strong, or it will simply get instantly dealocated after the function ends and mutableDict gets out of scope.
References are just pointers, setting one to nil will have no effect except in the following case: It is the last strong reference and other weak references still exist. In that case all the weak references will become nil. Strong properties will set the old value to nil, in effect sending a release call but this affects the REFERENCE, not the CONTENT of the reference.
As for the second question, it is quite confusing and I need more info about playbackType. You say it is an NSDictionary but NSDictionary doesn't have the property maxRange so it must be a type that you defined. You can't change the values of an NSDictionary either because it is immutable.
But here is a generic answer: If you pass a pointer to a mutable object as strong (or weak even) you will be able to change the content of the original. If you pass a pointer to a mutable object as a copy you will get a new object that doesn't affect the original.

Will ARC tell me when I must use __block?

AFAIK, __block is used when you're changing, inside the block, the address that a variable (declared outside the block) points to.
But, what if I'm changing the value that the variable points to but the pointer stays the same? E.g., what if I have NSMutableArray *array and am just doing [array addObject:object] inside the block? In this case, I'm not changing the pointer array, but I'm changing the value it points to. So, must I still use __block in declaring NSMutableArray *array?
You only need __block if you are changing the value of the variable.
I.e. if you have:
NSArray* foo;
You only need __block if you change the value of foo. Now, keep in mind that foo is nothing more than "a pointer to a thing that is typed NSArray". I.e. foo is effectively a 64 bit or 32 bit integer, depending on platform. If you change that integer, you need __block. If you don't, you don't need __block.
So, no, you don't need __block to call addObject: on the array since you aren't actually changing the value of foo.
If you were to do something like foo = (expression);, then you'd need __block.
(note that this is one of the reasons why concurrent programming under OO is so damned hard... it is exceptionally hard to define the "domain of variance" for any given execution path)

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.

Get pointer to class of instance variable in Objective-C

I have an object that has several properties. If I have a pointer to one of those properties, is it possible to get a pointer to the class instance to which that ivar belongs?
for example: foo.bar, where I know the address of bar, can the address of foo be found?
This seems related to: run time references but I didn't see any references that were quite what I'm looking for.
Thanks for your help!
First, you need to adjust your terminology a bit. You cannot have a pointer to a property, because a property is an interface to an object, specifying the format of the getter and setter methods.
If you had a pointer to the getter, a method (IMP) at best you could get back would be a pointer to the class, certainly you could not get back to an instance.
If you had a pointer to an ivar, I don't believe there is any way to get back to the containing object instance. If you had an array of all posible foos, it might be possible to ask each of them for a list of ivars, and get the address of each ivar and eventuallty find the instance in question that way.
The best solution is for bar to contain a parent reference to foo, so that foo.bar.foo will give you the answer you want. But it depends on what exactly you are trying to do. The normal Cocoa way for a lot of these things is to pass foo as well, as is done for many delegates. For example:
[obj foo:foo doSomethingWithBar:foo.bar];
Unless the object has a pointer back to it's "parent" or you explicitly track it yourself, I don't believe there's a way to resolve that. You'd really have to trace through memory to find what basically amounts to "who points to me". It's essentially the same problem as finding the previous node in a singly-linked list — you have to start from the beginning and stop when you reach the node that points to the node of interest.
The problem with trying to track down foo from the address to bar is that foo.bar is a pointer that contains the address of an object, and only foo calls it "bar". For simplicity's sake, imagine that foo is at address 0x1000, and foo.bar is at 0x1008 and points to another object at 0x2000. Now, if you have the address 0x2000, there's no easy way to know that 0x1008 points to it.
It's even more complicated if you imagine that N other addresses might also point to 0x2000, so even if you did scan memory, you wouldn't know whether the pointer belonged to an object, struct, local variable, or even was just a random pattern that happened to match the address you're looking for.
You could do it if you have a pointer to the instance variable itself, rather than the contents of the instance variable.
Foo * reference = [[Foo alloc] init];
Foo * foo == [[Foo alloc] init];
int * barptr = &(foo->bar);
Foo * baz = (Foo *)((char *)barptr - ((char *)(&(reference->baz)) - (char *)reference));