2015-04-11 1 views
0

Таким образом, это очень легко получить «адрес памяти» указатель объекта, а-ля ..Как разыменовать объект Objective-C через его адрес указателя/памяти?

id x = @"obj"; printf("'x' is at: %p", x);

'x' is at: 0x100b60048

Удивительно, но я не могу найти какой-либо ссылки как как выполнить «обратную» операцию. то есть. получить ссылку на указатель на объект, либо через адрес указателя шестигранной int, или это строковое представление ...

NSString * ptr = @"0x100b60048"; 
unsigned addr = 0; 
NSScanner * scn = [NSScanner scannerWithString:ptr]; 
[scn scanHexInt:&addr]; 

я наткнулся на следующий «путь», но а) не работает (он падает) и б) раздражает хрупкие чувства компилятора (он же, он выдает предупреждения, lol).

id z = (__bridge id)((void*)addr); 

Итак, что такое «правильный», современный, совместимый с ARC способ сделать это?

+1

Я предполагаю, что единственный правильный путь: не делайте этого.Но могу ли я спросить, для чего вам это нужно? – vikingosegundo

+0

Я хочу, чтобы передать ссылку на объект в виде строки. –

+2

это звучит чрезвычайно опасно. Почему ты бы так поступил? – vikingosegundo

ответ

1

Так что это работает. При этом мне было бы очень неудобно полагаться на это в моем проекте. Если эта переменная освобождается, прежде чем сканировать ее адрес, кто знает, что вы собираетесь получить. В этом отношении, я думаю, это нарушает критерий, совместимый с ARC, потому что кто знает, когда эта ссылка будет выпущена, что делает это очень опасным. Кроме того, тип безопасности полностью выходит из окна.

NSString *pointer = @"test"; 
NSString *address = [NSString stringWithFormat:@"%p",pointer]; 

NSString *retrievedObject; 
sscanf([address cStringUsingEncoding:NSUTF8StringEncoding], "%p", &retrievedObject); 
2

Итак, что такое "право", современный, ARC-совместимый способ сделать это?

Правильный путь? Не делай этого.

Чтобы объект оставался в памяти в приложении ARC'd, должна быть сильная ссылка на указанный объект (или вы должны сделать что-то действительно противное с CF API). И любой указатель в строке будет действителен только в течение всего срока действия приложения; выйти и перезапустить? Все адреса теперь фиктивные.

Так что, если вы действительно хотите, чтобы обратиться к случайному объекта в строку, а затем сделать это:

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

Таким образом, вы будете никогда не нужно бросать между int и ptr, вам не придется использовать тонну опасного typecasting, чтобы успокоить компилятор, и ваш код будет совместим с ARC.

+0

Я согласен и согласен с вами по всем вашим пунктам. Теоретическая задача, которую я себе представлял, хотя и включал «стороны», которые не имели бы доступа к такому «совместному» контейнеру, чтобы удерживать фактический объект. –

+0

@alexgray Затем все стороны должны иметь некоторое представление об общем ключе для доступа к реальному объекту. И если стороны существуют на разных машинах, разных сеансах приложений или, даже, при закрытии и открытии документа, то строковое представление адреса * не будет работать *. – bbum

0

Хорошо, хорошо я выяснить относительно безболезненный способ сделать это, так что я выложу его здесь дедовщины/придирки и даже, < вздоха> ... возможно приемочного ... Используя оригинальный вопрос-х переменные ...

/// this requires a "0x" formatted hex string            
ptr = [ptr hasPrefix:@"0x"] ? ptr : 
     [@"0x" stringByAppendingString:ptr]; 

uintptr_t hex = strtoull(ptr.UTF8String, NULL, 0); 
    id gotcha = (__bridge id)(void *)hex;