Objective-C - 更改传入对象指针的地址

SG1*_*SG1 5 c pointers objective-c

假设我有一个方法,如:

- (void)reassignPassedObject:(void *)block;
Run Code Online (Sandbox Code Playgroud)

它被称为

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

我想将“self”引用重新分配给另一个对象,如下所示:

- (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...)"
    }
}
Run Code Online (Sandbox Code Playgroud)

这可能吗?

看起来这应该是公平的游戏,因为我们只是在谈论重新分配指针。我会担心特定实现中的释放/保留。这里让我感到困惑的挑战是:

  • 它涉及 id 而不是直接指针
  • 它涉及一个块传递变量
  • 它涉及必须以某种方式重新分配 block() 中对象的地址,我们只能访问本地持有者对象。

想法?

Yuj*_*uji 5

首先,不要self在代码内部进行更改,除非在init...via开头self=[super init...]

我不知道你为什么要使用块,或者是什么促使你做这一切,但如果你坚持改变指针指向的内容,最标准的基于 C 的方法是将指针传递给变量。例如

-(void)changeObjectPointedBy:(id*)p{
        *p=@"foo";
}
Run Code Online (Sandbox Code Playgroud)

然后这可以用作

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

注意代码中的额外&*。在尝试滥用块之前,我建议您学习简单的 C。

如果您坚持使用块,我会这样做:

-(void)passMyObjToBlock:(void(^)(id))block
{
     block(@"foo");
}
Run Code Online (Sandbox Code Playgroud)

可以用作

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

或者,另一种方法是

-(void)reassignPassedObject:(id*(^)())block{
     id*holder=block();
     *holder=@"foo";
}
Run Code Online (Sandbox Code Playgroud)

进而

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

请注意“指向对象的指针”和“指向对象的指针的指针”之间的区别。为了更改 指向的内容self,您需要将指针传递self给函数。这是 C 的一个基本限制,如果不使用一对&and就无法做到这一点*