Получить указатель на класс переменной экземпляра в Objective-C - PullRequest
2 голосов
/ 05 августа 2009

У меня есть объект, который имеет несколько свойств. Если у меня есть указатель на одно из этих свойств, возможно ли получить указатель на экземпляр класса, к которому принадлежит этот ivar?

например: foo.bar, где я знаю адрес bar, можно ли найти адрес foo?

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

Спасибо за вашу помощь!

Ответы [ 3 ]

1 голос
/ 05 августа 2009

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

Если бы у вас был указатель на метод получения, метод (IMP), в лучшем случае вы могли бы получить обратно, был бы указателем на класс, конечно, вы не могли бы вернуться к экземпляру.

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

Лучшее решение для bar - содержать родительскую ссылку на foo, так что foo.bar.foo даст вам нужный ответ. Но это зависит от того, что именно вы пытаетесь сделать. Обычный способ какао для многих из этих вещей - также передать foo, как это делается для многих делегатов. Например:

[obj foo:foo doSomethingWithBar:foo.bar];
1 голос
/ 05 августа 2009

Если у объекта нет указателя на его "родительский объект" или вы явно не отслеживаете его самостоятельно, я не верю, что есть способ решить эту проблему. Вы действительно должны проследить через память, чтобы найти то, что в основном составляет «кто указывает на меня». По сути, это та же проблема, что и при поиске предыдущего узла в односвязном списке - вы должны начинать с начала и останавливаться при достижении узла, который указывает на интересующий узел.

Проблема с попыткой отследить foo от адреса до bar состоит в том, что foo.bar - это указатель, который содержит адрес объекта, и только foo называет его "bar". Для простоты представьте, что foo находится по адресу 0x1000, а foo.bar находится по адресу 0x1008 и указывает на другой объект в 0x2000. Теперь, если у вас есть адрес 0x2000, нет простого способа узнать, что 0x1008 указывает на него.

Еще сложнее, если вы представите, что N других адресов также могут указывать на 0x2000, поэтому даже если бы вы сканировали память, вы не знали бы, принадлежал ли указатель объекту, структуре, локальной переменной или даже просто случайный шаблон, который совпадает с адресом, который вы ищете.

0 голосов
/ 05 августа 2009

Вы можете сделать это, если у вас есть указатель на саму переменную экземпляра, а не на содержимое переменной экземпляра.

Foo * reference = [[Foo alloc] init];
Foo * foo == [[Foo alloc] init];
int * barptr = &(foo->bar);
Foo * baz = (Foo *)((char *)barptr - ((char *)(&(reference->baz)) - (char *)reference));
...