我正在通过 Instruments 运行我的应用程序并使用大量数据对其进行压力来完成它。仪器测试进展顺利,但压力测试是我遇到问题的地方。在不涉及太多细节的情况下,我为我的应用程序提供了越来越多的Core Data
它需要推断数据、制作图表并在地图上显示位置的事件MKMapView
实例。我从小规模开始,增加到 56000 个事件,它处理得很好,没有任何泄漏或内存警告(我为它处理这一切感到非常自豪)。
我的应用程序实现了 Dropbox API,以允许上传和下载模板和数据以实现同步目的。从我的应用程序上传的文件是从Core Data
to an NSDictionary
,然后到NSData
。我为数据创建一个临时文件夹,然后将该文件上传到 Dropbox,一切正常......正常。如果我尝试上传包含 56000 个事件的数据文件,则会崩溃。我已经记录了它并观察了数据的转换。它毫无问题地到达了最后一个事件,但是当它应该开始上传到 Dropbox 时,应用程序崩溃了,我一辈子都无法弄清楚原因。我看到日志上弹出内存警告。通常,它会进入 Level=1、Level=2、Level=1、Level=2,然后崩溃,这让我很困惑,因为它永远不会达到 Level=3。
我找到的大部分信息都在我在底部的编辑中。下面是一些相关代码:
- (void)uploadSurveys:(NSDictionary *)dict {
NSArray *templateArray = [dict objectForKey:@"templates"];
NSArray *dataArray = [dict objectForKey:@"data"];
NSString *filename;
NSLog(@"upload called");
if ([templateArray count] || [dataArray count]) {
if ([templateArray count]) {
// irrelevent code;
}
if ([dataArray count]) {
SurveyData *survey;
for (int i = 0; i < [dataArray count]; i++) {
BOOL matchExists = NO;
// ...... code to make sure no file exists in dropbox folder and creates new version if necessary;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = [self convertSurvey:survey];
dispatch_async(dispatch_get_main_queue(), ^{
[self uploadData:data withFilename:filename];
NSLog(@"converted and uploading");
});
});
}
}
}
[self convertSurvey:survey]
只是转换我的Core Data
反对NSData
.
- (void)uploadData:(NSData *)data withFilename:(NSString *)filename {
NSFileManager *manager = [NSFileManager defaultManager];
NSString *pathComponent = [NSString stringWithFormat:@"tempData.%@", filename];
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:pathComponent];
if ([manager createFileAtPath:path contents:data attributes:nil]) {
[self.restClient uploadFile:filename toPath:[NSString stringWithFormat:@"/%@", currentSearch] fromPath:path];
NSLog(@"uploading data");
}
}
任何帮助将不胜感激,我提前衷心感谢您。我只是想弄清楚我是否对大文件采取了错误的方法或者是否根本不允许。如果我必须拆分文件,那很好,但在我尝试解决方法之前,我更想知道发生了什么阻止我的应用程序执行此操作。再次感谢你。
更新:由于这个问题现在是发布我的应用程序的唯一障碍,因此我为此问题添加了赏金,以希望获得解决方案或解决方法。它将持续一周,之后给定时间我很可能会在上传文件时将其拆分,以确保不会达到明显的大小限制。这种方法并不理想,这就是为什么更好的解决方案非常受欢迎,但如果这不能带来更方便的东西,这是我的后备计划。
编辑:看来NSTemporaryDirectory
根本不参与其中。这是新的情况。正如您在上面的代码中看到的,NSData *data = [self convertSurvey:survey];
在辅助线程中调用(这不是问题)。我一直在记录创建的对象,并且知道它们已经到达最后一个,但从未想过检查并查看是否NSData
文件已返回。事实证明,事实并非如此。简而言之,我将所有核心数据对象转换为数组并将它们放入字典中(仅用于要转换的相关调查/数据)。这确实有效并且字典已创建。然后我创建一个NSData
文件使用NSData *data = [NSKeyedArchiver archivedDataWithRootObject:d];
where d
是我的字典。之后我立即打电话return data;
设置值NSData *data = [self convertSurvey:survey];
。既然如此,看来NSData
or NSKeyedArchiver
都是这里的错。根据苹果文档:
使用32位Cocoa,数据的大小理论上受到2GB的限制(实际上,因为内存会被其他对象使用,这个限制会更小);使用 64 位 Cocoa,数据大小受到约 8EB 的理论限制(实际上,该限制不应成为一个因素)。
我以较小的增量检查了文件大小,以查看故障发生的位置。我已经成功获取了 48.2MB 的数据,但不是 51.5MB,这让我相信问题发生在 50MB 左右,远低于理论限制NSData
(除非 iOS 和 OS X 在这方面存在差异)。
希望这个新信息将有助于解决这个问题