开发者

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 ta开发者_运维百科lking about reassigning pointers. I will worry about release/retain in a specific implementation. The challenge here that confuses me is:

  • It involves id instead of straight pointers
  • It involves a block-passed variable
  • It involves having to somehow reassign the address of the object inside block() where all we have access to is the local holder object.

Ideas?


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 *.


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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜