Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/103.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS在NSMutableDictionary中释放对象_Ios_Objective C_Automatic Ref Counting_Nsmutabledictionary - Fatal编程技术网

iOS在NSMutableDictionary中释放对象

iOS在NSMutableDictionary中释放对象,ios,objective-c,automatic-ref-counting,nsmutabledictionary,Ios,Objective C,Automatic Ref Counting,Nsmutabledictionary,在iOS 7.1的ARC应用程序中,我有一个单例类,它有一个NSMutableDictionary(属性是非原子,retain),其中键是字符串,值是NSMutableArray。该类在NSOperation子类的回调中设置此字典。一切似乎都很正常,直到过了一段时间(可能是几分钟或几个小时),NSMutableDictionary中的对象消失。通常情况下,应用程序都是在后台开发的,但要找到一个可复制的测试用例几乎是不可能的。然而,问题一直在发生 我如何进行调试?我见过查找泄漏的工具,但没有发现过

在iOS 7.1的ARC应用程序中,我有一个单例类,它有一个
NSMutableDictionary
(属性是
非原子,retain
),其中键是字符串,值是
NSMutableArray
。该类在
NSOperation
子类的回调中设置此字典。一切似乎都很正常,直到过了一段时间(可能是几分钟或几个小时),
NSMutableDictionary
中的对象消失。通常情况下,应用程序都是在后台开发的,但要找到一个可复制的测试用例几乎是不可能的。然而,问题一直在发生

我如何进行调试?我见过查找泄漏的工具,但没有发现过早释放的工具

代码:


在我看来,您希望使用一种更持久的方式来存储此
NSMutableDictionary
。将其存储在单例上并不能保证数据将永远保存。只要为应用程序分配了内存(实际上是单例本身)。当应用程序进入后台时,操作系统能够根据需要释放内存(正如@CodaFi所提到的)

我建议您使用核心数据存储这些数据,或者将其保存到一个文件中以便以后读取。还有其他选择(例如NSUserDefaults),但我可能需要更多地了解为什么要保留这些数据,才能真正知道最好的方法是什么

将此
NSMutableDictionary
保存到文件的简单方法是使用以下代码:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *plistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"myPlistFile.plist"];
[yourDictionary writeToFile:plistPath atomically:YES];
您可以使用以下代码检索数据(假设您使用从上面生成
plistPath
的相同方法):


也许你在做这样的事情:

NSMutableDictionary *newDict = yourDictionary;
然后删除
newDict的对象

newDict = nil;

这也将从
yourDictionary

中删除值,我觉得启用僵尸将是调试此问题并确定对象过早释放的原因的最佳方法。以下是僵尸对象的功能(引用苹果文档):

将解除分配的对象替换为“僵尸”对象,该对象会捕获任何使用该对象的尝试。当您向僵尸对象发送消息时,运行时会记录错误并崩溃。您可以查看回溯以查看触发僵尸检测器的调用链

要启用僵尸,请按CMD+Shift+,(逗号),然后转到诊断选项卡并勾选“启用僵尸对象”


希望这有帮助

您必须从类中分配内存

- (void)loadWithCompletion:(void (^)(BOOL succeeded))aBlock {
    self.queue = [[NSOperationQueue alloc] init];
    MyFetchObjectsOperation * op = [[MyFetchObjectsOperation alloc] init];
    op.successBlock = ^(NSMutableDictionary * allByCategory, NSMutableDictionary * allByName) {
        self.allObjectsByCategory = [[NSMutableDictionary alloc] initWithDictionary:allByCategory];
        self.allObjectsByName = [[NSMutableDictionary alloc] initWithDictionary:allByName];
        aBlock(YES);
    };

    op.failureBlock = ^(NSError * err) {
        aBlock(NO);
    };

    [self.queue addOperation:op];
}

如果应用程序在后台运行足够长的时间,操作系统就会将其关闭,如果你没有持久化任何内容,你就会从头开始。即使应用程序从未发送到后台,也会发生这种情况吗?一些代码将有助于确定原因。通常在发出内存不足警告时。我们清除了视图,但保留了数据……这看起来像是并发/竞争条件错误。这会帮助你发布一些代码。我相信即使应用程序没有被发送到后台,这种情况也会发生。我必须重新测试这一点,以确认这是耗时的,因为它不容易复制(但经常发生)
newDict = nil;
- (void)loadWithCompletion:(void (^)(BOOL succeeded))aBlock {
    self.queue = [[NSOperationQueue alloc] init];
    MyFetchObjectsOperation * op = [[MyFetchObjectsOperation alloc] init];
    op.successBlock = ^(NSMutableDictionary * allByCategory, NSMutableDictionary * allByName) {
        self.allObjectsByCategory = [[NSMutableDictionary alloc] initWithDictionary:allByCategory];
        self.allObjectsByName = [[NSMutableDictionary alloc] initWithDictionary:allByName];
        aBlock(YES);
    };

    op.failureBlock = ^(NSError * err) {
        aBlock(NO);
    };

    [self.queue addOperation:op];
}