这是一个简单的课程:
#import "One.h"
#import "Two.h"
@implementation DataFileRegistrar
static NSMutableDictionary *elementToClassMapping;
+ (void)load
{
[self registerClass:[One class] forElement:@"one"];
[self registerClass:[Two class] forElement:@"two"];
}
+ (void)registerClass:(Class)class forElement:(NSString *)element
{
if (!elementToClassMapping) {
elementToClassMapping = [NSMutableDictionary dictionaryWithObject:class forKey:element];
} else {
[elementToClassMapping setValue:class forKey:element];
}
}
+ (id)classForElement:(NSString *)element
{
return [elementToClassMapping valueForKey:element];
}
@end
问题是这个编译器消息:
objc[7172]: Object 0x6840720 of class __NSCFDictionary autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
任何想法发生了什么?
基本上,我想要一个带有几个类方法和一个静态字典的简单类。它总是在没有实例化的情况下使用。我想在应用程序启动后立即将它用于一些事情,然后我想释放它的内存。我以为ARC可以解决这个问题。
答案 0 :(得分:5)
您不应在静态变量上使用自动释放的对象。
更改行......
elementToClassMapping = [NSMutableDictionary dictionaryWithObject:class forKey:element];
到
elementToClassMapping = [[NSMutableDictionary alloc] initWithObjects:[NSArray arrayWithObject:class] forKeys:[NSArray arrayWithObject:element]];
如果没有创建自动释放池,也不要从第二个线程调用+ (void)registerClass:(Class)class forElement:(NSString *)element
。
答案 1 :(得分:4)
您的班级“+load
正在调用调用autorelease
的方法。
您的课程已在main
之前加载。
您可以在+load
中明确创建自动释放池:
+ (void)load
{
@autoreleasepool {
[self registerClass:[One class] forElement:@"one"];
[self registerClass:[Two class] forElement:@"two"];
}
}
但是,在main
中创建任何线程之前,通常最好保证程序的初始化和加载顺序:
int main(int argc, const char * argv[]) {
@autoreleasepool {
[DataFileRegistrar initializeStaticStuff];
...
答案 2 :(得分:-1)
你在做什么就是把字典放在堆栈上(坦率地说是愚蠢的,因为你有很多方法不这样做)并且它会泄漏,因为它永远不会从堆栈中释放出来。
创建NSDictionary是为了与自动释放池一起使用(是的..我知道有些情况下使用静态的更好但是这些情况非常罕见)
在界面中声明NSMutableDictionary *elementToClassMapping;
,一切都会正常工作