Objective-C - изменить адрес переданного указателя объекта - PullRequest
4 голосов
/ 02 августа 2011

Допустим, у меня есть такой метод:

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

, и он вызывается как в

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

Я хочу переназначить ссылку '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...)"
    }
}

Возможно ли это?

Похоже, что это должна быть честная игра, поскольку мы просто говорим о переназначении указателей.Я буду беспокоиться о выпуске / сохранении в конкретной реализации.Проблема, которая меня смущает, такова:

  • Она включает в себя идентификатор вместо прямых указателей
  • Она включает в себя переменную, переданную блоком
  • Она включает в себя необходимость каким-либо образом переназначитьадрес объекта внутри block (), к которому у нас есть доступ - это локальный объект-держатель.

Идеи?

Ответы [ 2 ]

3 голосов
/ 02 августа 2011

Прежде всего, не изменяйте self внутри вашего кода, если только в начале init... через self=[super init...].

И я понятия не имею, почему вы хотите использовать блоки или что побуждает вас делать все это, но если вы настаиваете на изменении того, на что указывает указатель, самый стандартный способ на основе C - это передать указатель на переменная. например,

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

Тогда это можно использовать как

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

Обратите внимание на дополнительные & и * в коде. Прежде чем пытаться злоупотреблять блоками, я бы посоветовал вам изучить простой C.

Если вы настаиваете на использовании блока, я бы сделал:

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

, который можно использовать как

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

Или, другой способ -

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

, а затем

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

Обратите внимание на различие между «указателем на объект» и «указателем на указатель на объект». Чтобы изменить то, на что указывает self, вам нужно передать указатель на self функции. Это фундаментальное ограничение C, и вы не можете сделать это без использования одной пары & и *.

.
1 голос
/ 02 августа 2011

Хотя вы можете назначать себя (это обычная практика в методе init), то, что вы делаете, кажется очень, очень неправильным.

A отличный пост о Какао с любовью описывает, как все это работает в Objective-C и, возможно, может пролить некоторый свет на это.

Вы пытаетесь достичь чего-то конкретного?Или вы просто надеетесь лучше понять язык?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...