__unsafe_unretained NSString struct var

我试图创build一个结构,它有不同types的几个不同的variables。

几个types是NSString,但试图这样做是错误的

ARC forbids Objective-C objects in structs or unions

所以读了关于我认为合理的补充错误

 __unsafe_unretained 

在NSString声明之前,我不知道会有什么后果,我有一个快速的阅读,发现这个详细的post有关的差异

  • __强大
  • __弱
  • __unsafe_unretained

然而,它仍然含糊其辞的NSString是什么在一个结构与__unsafe_unretained它的结构,并希望有人可以告诉我怎么回事,我需要考虑在未来有关记忆和停止任何泄漏。

任何帮助,将不胜感激。

假设在ARC下,你可以像这样声明一个结构体:

 typedef struct { __strong NSObject *someObject; int someInteger; } MyStruct; 

那么你可以写这样的代码:

 MyStruct *thing = malloc(sizeof(MyStruct)); 

问题: malloc不会填满它返回的内存。 所以thing->someObject是一些随机值 – 不一定是NULL。 然后你给它赋值如下:

 thing->someObject = [[NSObject alloc] init]; 

在封面之下,ARC会把它变成这样的代码:

 NSObject *temporary = [[NSObject alloc] init]; [thing->someObject release]; thing->someObject = temporary; 

这里的问题是你的程序只是release到一些随机值! 你的应用程序可能会崩溃在这一点上。

您可能会说ARC应该识别对malloc的调用,并将someObject设置为NULL来防止出现这种情况。 问题是malloc可能被包装在其他函数中,如下所示:

 void *myAllocate(size_t size) { void *p = malloc(size); if (!p) { // malloc failed. Try to free up some memory. clearCaches(); p = malloc(size); } return p; } 

好了,现在ARC也必须知道你的myAllocate函数了…这可能在你作为二进制文件得到的静态库里面。

您的应用程序甚至可能拥有自己的内存分配器,它们可以在不使用freemalloc情况下循环旧分配。 所以即使在返回之前更改malloc以填满内存也不行。 ARC将不得不知道你的程序中的任何自定义分配器。

要做到这一点是非常非常困难的。 所以ARC的创造者只是放弃了,并说:“忘了它。 我们不打算让__strong__weak引用在结构中。

这就是为什么只有在使用__unsafe_unretained来告诉ARC“不要试图pipe理这个引用的对象的所有权”的情况下,才能将一个对象指针放入一个结构体中。

您可以尝试使用包含__unsafe_unretained对象引用的结构,也许使用CFRetainCFRelease手动保留并释放它们。 然后你可以创build一个这样的结构数组。 这很容易出错,所以如果分析器告诉你这对于性能来说至关重要,那么你只能这样做。

相反,只需创build一个新的Objective-C类而不是一个结构体。 给这个类一个@property为你将在结构中放置的每个字段。 使用NSMutableArray来pipe理这个新类的实例的数组。

只是更多的思考…

如果你真的需要非目标代码中的ARC指针,你可以在C ++中使用它们。

事实上,你可以在所有的标准模板容器中存储ARC指针,它们仍然保留(哈哈)它们的正确的语义。

 struct Foo { NSDictionary *dictionary; NSString *string; __weak UIViewController *viewController; }; std::list<UIView*> views; 

由于编译器将ARC指针视为具有非平凡构造函数的对象,因此它们可以具有正常的语义。

他们所有的ARC荣耀将被神奇地处理。

ARC只是喜欢抱怨! 实际上,我们必须从历史的angular度来看待这个问题。 在旧式的“手工参考计数”环境中,编译器并没有抱怨,因为它知道所有相关的内存将成为你的工作,而你自己的工作。 但是,当Apple引入自动引用计数时,情况发生了变化,因为编译器需要更多地分析对象是什么types以及包含什么types,以便知道如何有效pipe理对象的内存。 当你将一个Objective-C对象放入一个C-struct中时,你就会在编译器中大声疾呼,因为一个结构意味着你将拥有和pipe理它里面的项目的内存(这个和ARC不会不要碰malloc和免费)。 这是__unsafe_unretained进来的地方。有了它,我们告诉编译器,任何和所有的内存操作将是你的责任,就像在MRC。 ARC从字面上“不能保证对象指针的安全性”在释放之后是零,所以它使得你明确地声明它是这样的。

如果你想避免所有这些废话,只要把你的结构变成一个轻量级的类,并正常地声明你的对象。 毕竟,Objective-C中的类只是C结构(ish),并且引入了大量的Apple魔力。

不要把客观的C对象放在结构中。 这就是为什么Obj C支持类。 你正在编码C.