__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
函数了…这可能在你作为二进制文件得到的静态库里面。
您的应用程序甚至可能拥有自己的内存分配器,它们可以在不使用free
和malloc
情况下循环旧分配。 所以即使在返回之前更改malloc
以填满内存也不行。 ARC将不得不知道你的程序中的任何自定义分配器。
要做到这一点是非常非常困难的。 所以ARC的创造者只是放弃了,并说:“忘了它。 我们不打算让__strong
和__weak
引用在结构中。
这就是为什么只有在使用__unsafe_unretained
来告诉ARC“不要试图pipe理这个引用的对象的所有权”的情况下,才能将一个对象指针放入一个结构体中。
您可以尝试使用包含__unsafe_unretained
对象引用的结构,也许使用CFRetain
和CFRelease
手动保留并释放它们。 然后你可以创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.