Objects with the same name, what does that mean? - objective-c

I thought I had a decent understanding of objects, but I guess not. What happens when two objects are the same name? They are both pointing to the same location in memory? So if I had one class that said:
SomeClass *someObject = [SomeClass new];
someObject.text = #"test";
And another class instantiates the same object with the same name:
SomeClass *someObject = [SomeClass new];
someObject.textColor = [UIColor redColor];
This would modify the same object to be a red text that says "test" right ?
Thanks!
~Carpetfizz

No, those two pointers point to two different objects in the memory. It doesn't matter if they have the same name. They were allocated and initialized separately in two different classes.
Btw, you should never use the new method to allocate and initalize the object. The new message is discouraged, as allocation and initialization are two different processes. You should use this instead:
SomeClass *someObject = [[SomeClass alloc] init];

Nope. Just because two variables happen to share the same name does not mean they share the same memory location. When this compiles, the compiler strips the variable names (but not the class names) and calculates memory offsets and messages instead of names and classes. Besides, as a local variable, as soon as they pass out of scope -most likely at the end of each function that created them- they will be destroyed immediately.

No. You can't do that.
Any modern-day compiler will attempt to strangle you before compiling that code - for that exact reason: It doesn't know what to do!
Even if you could get the compiler to make it work, just because the two objects have the same name doesn't mean they have the same memory address.

Related

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

Assign or retain in cocos2d and objective C

Here's my current situation:
I have a NSMutableArray named dictKeyArray which I assign a property with #property(nonatomic,retain)NSMutableArray *dictKeyArray
I synthesize my mutable array in the implementation file.
Later, I have a dictionary name storeDict. I assign all the keys of the dictionary to the dictKeyArray like so:
dictKeyArray = [[storeDict allKeys] mutableCopy];
Now I use this dictionary later in my implementation file. However, when it comes to releasing it, I release it once in my dealloc method. When checking with instruments, a leak shows up! Why is dictKeyArray leaking? Should I be using assign instead of retain?
I'm still not clear on what the difference is exactly...
thank you!
You have to send it an
[[[storeDict allKeys] mutableCopy] autorelease];
Just to make this clear: mutableCopy does the same as alloc meaning you are claiming ownership of the object in question. You have to decrease the retainCount by one.
By the way: You should use the accessor you wrote for it. You are just assigning it to your iVar at the moment. If you want to make your accessors work, you will have to use something like
object.dictKeyArray = ...;
in general. Or here (as mentioned by dreamlax)
self.dictKeyArray = ...;
because you are referring to an object of this specific class the code is in.
Only this way you are ensuring your object is properly retained by your accessor. Otherwise writing the accessor code doesn't make sense at all because it never gets called.
Please note: As Josh said in the comments, your code should be valid (at least from my point of view). What I suggested is a solution that is not as error-prone as yours because you adhere to the rules (could save you from headache in the near future).
You should be using self.dictKeyArray = .... Without the self. you are accessing the instance variable directly, bypassing any memory management benefits of properties, but, remember that you own the result of mutableCopy, and assigning to a property that also takes ownership will result in double-ownership, so use:
self.dictKeyArray = [[[storeDict allKeys] mutableCopy] autorelease];

When and when to not allocate memory to objects

NSArray *array = [dictionary objectForKey:#"field"];
and
NSArray *array = [[NSArray alloc] initWithArray:[dictionary objectForKey:#"field"]];
I see both kind of approaches very frequently in objective C code.
When tried to understand, I found both of them used in similar situation too, which makes contradiction. I am not clear on when I should use 1st approach and when 2nd one?
Any idea?
Detailed explanation and useful references are moms welcome.
First off, those two examples are doing slightly different things. One is retrieving something from an existing dictionary and one is creating a new array by retrieving something from an existing dictionary (the value of that key is an array).
But, if you're asking the difference between getting objects by alloc vs. convenience methods. ([NSString alloc] init vs [NSString stringWith ...), by convention, you own anything that you call alloc, new copy or mutableCopy on. Anything that you call that is not those, is autoreleased.
See the memory guide here. Specifically, look at the rules.
Getting an autoreleased object means it will go away at some point in the near future. If you don't need to hold onto outside the scope of that function, then you can call autorelease on it or use one of the convenience methods that's not alloc, etc...
For example:
// my object doesn't need that formatted string - create the autoreleased version of it.
- (NSString) description {
return [NSString stringWithFormat:#"%# : %d", _title, _id];
}
// my object stuffed it away in an iVar - I need the retained version of it. release in dealloc
- (void) prepare {
_myVal = [[NSString alloc] initWithFormat:"string I need for %d", _id];
}
In the first example, I created a convenience methods for others to call, my class doesn't need that object beyond the scope of that method so I create the autoreleased version of it and return it. If the caller needs it beyond the scope of his calling method, he can retain it. If not he can use it and let it go away. Very little code.
In the second example, I'm formatting a string and assigning it to an iVar variable that I need to hold onto for the lifetime of my class so I call alloc which will retain it. I own it and releasing it eventually. Now, I could have used the first version here and just called retain on it as well.
You have a fundamental misunderstanding of allocations versus instance methods.
The first example, NSDictionary's -objectForKey method, returns id, not an instance of NSDictionary, therefore it does not allocate or initialize the variable.
The second, however is the classic retain part of the retain-release cycle.
The two methods are fundamentally equal (if we are to assume that array is alloc'd but empty in the first, and nil in the second), and both get ownership of the array object. I would go with the second, as it guarantees a reference, and it's shorter.
What I think you're confusing this with are new and convenience methods. Convenience methods (like NSNumber's +numberWithInt:, NSString's +stringWithFormat:, and NSMutableArray's +array), return an autorelease instance of the class (usually). New takes the place of alloc and init in just one word.

Objective-c object releasing patterns

I've run into some unfamiliar Objective-c memory management code. What is the difference between:
// no property declared for myMemberVariable in interface
id oldID = myMemberVariable;
myMemberVariable = [MyMemberVariable alloc] init];
[oldID release];
and:
// (nonatomic, retain) property is declared for myMemberVariable in interface
self.myMemberVariable = [[MyMemberVariable alloc] init];
Thanks!
The second is technically incorrect, but the first probably stems from someone yet to embrace Objective-C 2.0 property syntax. It was added relatively recently if you're a long-time OS X developer (or an even-longer-time NextStep/OS X developer), so you do see people not using it without gaining any benefit or detriment by not doing so.
So the first is basically the same as:
[myMemberVariable release];
myMemberVariable = [[MyMemberVariable alloc] init];
Given that you have a 'retain' property, the correct version with the setter should be:
// this'll be retained by the setter, so we don't want to own what we pass in
self.myMemberVariable = [[[MyMemberVariable alloc] init] autorelease];
In the first example, you've got an instance variable. In the second, a property with auto memory management attributes (as indicated by the retain).
In the first example, you're allocating an object, assigning it to an instance variable, then releasing it. It also appears that you're also leaking the object that was previously assigned to it since you don't explicitly release it. (Maybe it's autoreleased, can't tell here).
In the second example, you're allocating an object, and assigning it to a property that is retaining it. This means you're going to leak it unless you explicitly release/autorelease it.
self.myMemberVariable = [[[MyMemberVariable alloc] init] autorelease];
or
MyMemberVariable *m = [[MyMemberVariable alloc] init];
self.myMemberVariable = m;
[m release];
It's much better to use properties as you get (most) memory management for free. For example, you won't have to worry about freeing a reference before assigning a new one.
The first form does not use properties. I don't see a good reason not to do:
[myMemberVariable release];
myMemberVariable = [[MyClass alloc] init];
Since the old value is definitely not the same as the new one, so there is no chance any old value is released before it can be retained again.
Properties have the advantage that, in newer compilers, they are synthesized by the compiler and simply do the right thing, i.e. they know how to retain the new and release the old value, if the type is one that must be retained or copied. This is not necessary for types like int, float, etc., since these are simple value types.
In other words, if you use dot notation, either on self or on some other object, you access the property and in fact call either the getter or setter methods, depending on the direction of assignment.
If you access the ivar (member variable) directly, you don't have the protection from the property and have to code retain/release yourself.
You can also write your own setters and getters, and then you'll also have to take care of memory management, where it applies. It does, however, give you more flexibility. You could log items, check the validity of the input, update internal state variables, etc.

Memory cleanup on returned array from static method (objective-c)

In objective-c, I have a utility class with a bunch of static methods that I call for various tasks. As an example, I have one method that returns an NSArray that I allocate in the static method. If I set the NSArray to autorelease, then some time later, the NSArray in my calling method (that is assigned to the returned pointer) losses it's reference because the original form the static method is cleaned up. I can't release the NSArray object in the static method because it needs to be around for the return and assignment.
What is the right way to return an object (like the NSArray) from a static class, and have it hang around for the calling class, but then get cleaned up later when it is no longer needed?
Do I have to create the object first in the caller and pass in a pointer to the object and then return that same object form the static method?
I know this is a basic O-O problem, I just never had this issue in Java and I do not do much C/C++.
Thanks for your help.
Your autorelease is correct in the return just retain it when you call the static method.
NSArray *data = [[StaticClass getArray] retain];
If you have a property for the place your assigning the return value to, you can just do self.data = .. and the retain is automatic.
Please take the time to read over the rules. These apply to all of the frameworks you'll be using, and should apply to your code as well. Burn these into your head, and they'll become second nature. Thankfully, it's not complex, rather simple.
It's quite simple. If you do not own an object, it will go away at some indeterminate point in the future. In your case, the "indeterminate" point is when the autorelease pool gets drained, which in the normal case, is at the end of processing the current event.
If you want an object to hang around, you need to own it. The memory management rules referred to by jer will tell you exactly how you get ownership of an object. In this case, you need to retain the object. You must then, of course, release it later when you have done with it.
Regards your comment to Matt's answer. Your code is this:
for (NSString * date in dateList)
{
[historyList addObject:[[BIUtility historyForDate:date] retain]];
}
and
+ (NSArray *) historyForDate:(NSString *)date
{
NSMutableArray * ret = [[[NSMutableArray alloc] init] autorelease];
}
The first thing you need to know is that collections retain their members, so, in fact, your retain of the historyForDate is unnecessary. You don't want to own that object, historyList does. If it's disappearing, it's probably because historyList itself is being deallocated (because you don't own it) or is nil.
By the way, historyForDate: does nothing with the date. Is that correct?