SG1
SG1

Reputation: 2891

Objective-C - Change the address of a passed-in object pointer

Let's say that I've got a method like:

- (void)reassignPassedObject:(void *)block;

and it's called as in

NSLog(@"self 1: %@", self);
[myController reassignPassedObject:^(){return self;}];
NSLog(@"self 2: %@", self);

I want to reassign the 'self' reference to another object, like this:

- (void)reassignPassedObject:(void *)block {
    id holder = block();

    if ( YES ) {
        id newObject = nil; //or NSString or NSArray
        //do something such that output second log is "self 2: (newObject...)"
    }
}

Is this possible?

It seems like it should be fair game since we're just talking about reassigning pointers. I will worry about release/retain in a specific implementation. The challenge here that confuses me is:

Ideas?

Upvotes: 5

Views: 2098

Answers (2)

Yuji
Yuji

Reputation: 34185

First of all, don't change self inside your code, unless in the beginning of init... via self=[super init...].

And I have no idea why you want to use blocks, or what motivates you to do all this, but if you insist on changing what a pointer points to, the most standard C-based way is to pass the pointer to the variable. e.g.

-(void)changeObjectPointedBy:(id*)p{
        *p=@"foo";
}

Then this can be used as

NSString*q=@"bar";
[self changeObjectPointedBy:&q];
NSLog(@"%@",q); // prints "foo"

Note the extra & and * in the code. Before trying to abuse blocks, I'd recommend you to learn straightforward C.

If you insist on using a block, I would do:

-(void)passMyObjToBlock:(void(^)(id))block
{
     block(@"foo");
}

which can be used as

__block NSString*p=@"bar";
[self passMyObjToBlock:^(id obj){
       p=obj;
}];
NSLog(@"%@",p); //prints "foo"

Or, another way is to

-(void)reassignPassedObject:(id*(^)())block{
     id*holder=block();
     *holder=@"foo";
}

and then

id* pointerToSelf=&self;
[foo reassignPassedObject:^(){return pointerToSelf}];
// self is now @"bar"

Note the distinction between a "pointer to the object" and a "pointer to the pointer to the object". In order to change what is pointed to by self, you need to pass the pointer to self to the function. This is a fundamental limitation of C, and there is no way you can do this without using one pair of & and *.

Upvotes: 5

Ben Scheirman
Ben Scheirman

Reputation: 40961

While you can assign self (it is common practice to do so in the init method) what you're doing seems very, very wrong.

A great post on Cocoa With Love describes how all this works in Objective-C and could probably shed some light on this.

Are you trying to accomplish something specific? Or are you just hoping to understand the language better?

Upvotes: 1

Related Questions