如何通过指针/内存地址取消引用Objective-C对象?

时间:2015-04-11 11:57:58

标签: objective-c pointers memory-management runtime nsobject

因此,很容易得到一个对象指针的“内存地址”,ála..

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];

我确实遇到过以下“方式”,但它a)不起作用(它崩溃)和b)感谢编译器的脆弱感受(又称,它发出警告,哈哈)。

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

那么,什么是“正确”,现代,ARC兼容的方式来做到这一点?

3 个答案:

答案 0 :(得分:2)

  

那么,"是什么",现代的,与ARC兼容的方式呢?

正确的方法?不要这样做。

对于在ARC应用程序中保留在内存中的对象,需要强烈引用所述对象(或者你必须使用CF API做一些非常讨厌的事情)。任何指针在字符串中只会在应用程序的生命周期内有效;退出并重启?所有地址现在都是虚假的。

所以,如果你真的想引用字符串中的随机对象,那么这样做:

  • 将对象粘贴在字典中,并将NSNumber或NSString作为键(您甚至可以使用对象的地址作为值,但我建议不要使用它,因为地址不会在应用程序重新启动后生效你可能有一天会想要坚持那个词典)
  • 解析字符串时,提取密钥并查找对象

这样,你就不必在int和ptr之间进行转换,你不必使用大量危险的类型转换来安静编译器,你的代码将与ARC兼容。

答案 1 :(得分:1)

所以这很有效。话虽如此,在我的一个项目中依赖于此,我会感到非常不舒服。如果在扫描其地址之前释放该变量,谁知道您将获得什么。在这方面,我想这打破了“ARC兼容”标准,因为谁知道什么时候该参考将被释放,这使得这非常危险。此外,类型安全完全没有窗外。

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

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

答案 2 :(得分: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;