Pass object between classes and copy of object

Discussion in 'Mac Programming' started by donnib, Jun 25, 2010.

  1. donnib macrumors newbie

    Joined:
    Oct 13, 2009
    #1
    Hi, I have two classes, classA and classB. I have objectC in classA that i want to pass to classB. classB will take a copy of the objectC, make some changes then give the object back so classA can use objectC with the new changes. Here is what i do :

    1. Create objectC by doing this : classC *objectC = [self.rows objectAtIndex:0]
    2. Create an object of classB : classB *objectB = [[classB alloc] init];
    3. Now i give objectB an reference to objectC by setting an property of type classC in classB in this way : objectB.objectC = objectC (i called the name same in both classes).
    4. Now that classB has an reference to objectC which came from classA i make a copy of this object by doing this : [self setCopyObjectC:[objectC copy]]. (copyObjectC is an property of type classC just as objectC is).
    5. Now i have a copy of the objectC in copyObjectC. I now make some changes to copyObjectC and when i am done i want to give the changes back to the original object which came from classA and that was objectC so i do this : [self setObjectC: copyObjectC].

    Now comes the problem. I have studied the console and i see the memory addresses that are used. I see that i actually give objectC a new pointer to some new memory address which i suppose is correct because i have changed the object but when i debug in classA and i look at the objectC from there it still points to a wrong memory address. Why is that ? What am i misunderstanding ? My problem is that i can't see the changes that i made to objectC. It's still the old object.

    donnib
     
  2. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    I'll give you my input, but I'm not really sure what you are trying to accomplish here.

    Name your objects something sensible. I have no idea how these objects should actually interact, what their individual purposes are, etc. This makes it harder to reason about the problem at hand. This also applies to the naming of your member variables make it clear what purpose the member variable is serving, not what it is.

    Now that that is out of the way, I am going to very briefly explain the Objective-C object model, because I am afraid you do not understand it.

    classC *objectC ...
    This is the declaration of a primitive. It's type is a pointer to an Object of type classC. A pointer is a memory address, and for primitive types when you dereference a pointer this evaluates to the type they point to, with the value stored at this memory address.

    ... [[classB alloc] init] ...
    This does two things. It allocates memory on the heap for an Object of type classB. It then returns the pointer to this memory. It then passes the init message to the Object at the memory address stored in this pointer, and init either returns this same memory address, or in some cases, a new one. The result of this is a pointer to an address in memory where one will find an instance of classB.

    You say "i give objectB an reference to objectC" which seems to indicate that you sort of understand what is going on. You're storing the value of the pointer to objectC in a variable in objectB, but there is only one objectC out there. This means that any changes you make to the Object "out there" in memory will be reflected when you access that object through any pointer you have to it.

    If I understand your intention correctly, you do not need to make a copy of the Object pointed to by objectC. Just change the object, and when you access it through any of the pointers you will see this change reflected.

    If you have some other intention, explain it clearly and we will try to help more.

    -Lee
     
  3. donnib thread starter macrumors newbie

    Joined:
    Oct 13, 2009
    #3
    Thank you very much Lee for taking the time to reply.

    Yes you are right about the naming. I can assure you that this is not the naming i have in my code but something i made up because it is too complicated to pick the code out of my project so i made this example up.

    Anyway i was guessing that someone would ask me why even make a copy and make changes to the original one. Well the answer is that i make a copy and the user makes some changes which i want to cancel if the user does not want to save and that's why i want to use copy because it's convenient.

    What i don't understand is why i loose my data on the way when i set the original reference to point to the new copy. What i think i want is that i want the original pointer to point to some new data. I would have suspected that it would work but i am missing some understanding here i guess.

    donnib
     
  4. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #4
    OK, so we've gotten some of the big picture stuff out of the way. You are passing methods to self to set objectC to the altered copy you made. Where are these being called? Is self objectA if so, is it's implementation of setObjectC correct? Is copyObjectC definitely the "altered" copy at the point that you call setObjectC? Did you, perhaps, only set copyObjectC to the new copy object in objectB, but not objectA?

    -Lee
     
  5. donnib thread starter macrumors newbie

    Joined:
    Oct 13, 2009
    #5
    Hi Lee,
    Sorry for the late answer. I have tried to do make an example of the code so here it comes :

    Start with myMethod from classA and you should end in doSomething in classB

    Code:
    [B]classA.h[/B]
    
    #import <Foundation/Foundation.h>
    
    @interface classA : NSObject {
    	NSMutableArray *rows;
    }
    
    @property(nonatomic,retain) NSMutableArray *rows;
    
    - (void)myMethod;
    
    [B]classA.m[/B]
    
    - (void)myMethod {
    	classC *objectC = [self.rows objectAtIndex:0]
    	classB *objectB = [[classB alloc] init];
    	objectB.objectC = objectC;
    	[objectB load];
    }
    
    [B]classB.h[/B]
    
    #import <Foundation/Foundation.h>
    
    @interface classB : NSObject {
    	classC *objectC;
    	classC *copyObjectC;
    }
    
    @property(nonatomic,retain) classC *objectC;
    @property(nonatomic,retain) classC *copyObjectC;
    
    - (void)doSomething;
    - (void)load;
    
    [B]classB.m[/B]
    
    - (void)load {
    	[self setCopyObjectC: [objectC copy]];
    	[self doSomething];
    }
    
    - (void)doSomething {
    	//now i change something to copyObjectC and when done i do next line
    	[self setObjectC:copyObjectC]; 	//i expect now that the changes i made to copyObjectC are reflected all the way in 
    //classA object objectC.
    }
    
     
  6. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #6
    Ok, I see what's going on now.

    You are replacing the pointer in classB with the pointer to your copy. This has no affect whatsoever on the object A is pointing to. You've altered a pointer in B, but this doesn't change the object objectC points to or its copy at all. What you are wanting to do is alter the object at the other end of the objectC pointer, which will be reflected anywhere that has a pointer. In classC you could have a setUsingModel: method that takes another instance and sets all ivars to those in the model. You could then invoke this on the object pointed to by objectC, passing the altered copy as the model.

    It sounds like you still aren't totally clear on where an object lives, and what a pointer to it gets you. A pointer is just a value, say 0xA4. This points to a position in memory. The type of the pointer tells you what sort of thing you'll find at that memory address. The pointer is not the object. Changing the memory address does not do anything to the object in memory at its old position. Anything else pointing to the old memory position aren't going to know or care that you also had a pointer to it, and now you don't.

    In Objective-C there are no local Objects. They ALL live on the heap, and all of your local references to them will be via a pointer. The only way to act on them is to pass messages by way of a pointer.

    -Lee
     
  7. donnib thread starter macrumors newbie

    Joined:
    Oct 13, 2009
    #7
    Hi Lee,
    Thanx for the reply, i understand now what the problem is but i am unsure how to implement it. As far as i understand you are proposing that i make a method in classC that takes as argument an object of type classC and then in the method i go thru all variables and replace the values from the copied object which i get from as an argument.

    Let me know if understand this correct.

    donnib
     
  8. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
  9. donnib thread starter macrumors newbie

    Joined:
    Oct 13, 2009
    #9
    ok will do that, thanx for your help
     

Share This Page