我正在尝试创建一个结构,其中包含几个不同类型的不同变量。
其中几种类型是NSString,但尝试这样做会导致错误
ARC forbids Objective-C objects in structs or unions
因此,阅读有关错误的信息,我认为添加
是明智的__unsafe_unretained
在NSString声明之前但是我不知道这会产生什么影响,我已经快速阅读并发现了这个详细的post关于
的差异然而,对于一个带有__unsafe_unretained的结构中的NSString是什么仍然有点模糊,并希望有人可以告诉我发生了什么以及我将来需要考虑的内存和停止任何内容泄漏。
任何帮助将不胜感激。
答案 0 :(得分:10)
假设在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“不要尝试管理这个引用的对象的所有权”,你只能将对象指针放入结构中。
您可以尝试使用包含__unsafe_unretained
对象引用的结构,可能使用CFRetain
和CFRelease
来手动保留和释放它们。然后,您可以创建此类结构的数组。这很容易出错,因此只有在探查器告诉您它对性能至关重要时才应该这样做。
相反,只需创建一个新的Objective-C类而不是结构。为您在结构中放置的每个字段赋予类@property
。使用NSMutableArray
来管理这个新类的实例数组。
答案 1 :(得分:3)
更多值得思考的东西......
如果你真的需要非Objective-c代码中的ARC指针,你可以在C ++中原生使用它们。
实际上,您可以将ARC指针存储在所有标准模板容器中,并且它们仍然保留(ha ha)其正确的语义。
struct Foo {
NSDictionary *dictionary;
NSString *string;
__weak UIViewController *viewController;
};
std::list<UIView*> views;
由于编译器将ARC指针视为具有非平凡构造函数的对象,因此它们可以具有正常的语义。
他们所有的ARC荣耀都会被神奇地处理掉。
答案 2 :(得分:2)
__unsafe_unretained
的用武之地。有了它,我们告诉编译器任何和所有的内存操作都是你的责任,就像在MRC中一样。 ARC字面上并不能保证安全&#34;取消分配后对象的指针为nil,因此它会让你明确地声明它。
如果你想避免所有这些废话,只需将你的结构化成一个轻量级的类并正常声明你的对象。毕竟,Objective-C中的类只是C-structs-(ish),其中引入了很多Apple魔法。
答案 3 :(得分:-3)
不要将目标C对象放在结构中。这就是为什么Obj C支持课程。你正在编码C.