3

我需要下载并解析 40mb 的 json。现在我正在使用 AFJSONRequestOperation,它在旧设备上会导致内存警告和崩溃。应该怎么做?我认为正确执行此操作的唯一方法是流式传输 json,但我不知道如何执行此操作或哪个库最好。请提供例子。非常感谢!

4

2 回答 2

4

对于任何有同样问题的人,我是这样解决的: 1. 使用 AFHTTPRequestOperation 的输出流将 JSON 文件下载到本地存储。2. 使用 YAJLParser 解析小块 NSData。

结果:我在 iPad (1) 上用 50mb json 测试它,没有任何内存警告(内存大约 10mb)。

例子:

            NSError *error = nil;
         NSData *data = [NSData dataWithContentsOfFile:path
                                               options:NSDataReadingMappedAlways | NSDataReadingUncached
                                                 error:&error];
         YAJLParser *parser = [[YAJLParser alloc] initWithParserOptions:YAJLParserOptionsAllowComments];
         parser.delegate = self;
         [parser parse:data];
         parser.delegate = nil;
         parser = nil;

YAJLParser 代表:

// first declare in header file NSMutableArray *stack and NSString *mapKey
- (void)parserDidStartDictionary:(YAJLParser *)parser
{
    NSString *dictName = mapKey;
    if (mapKey == nil)
    {
        dictName = (stack.count == 0) ? @"" : [stack lastObject];
    }
    [stack addObject:(dictName)];
}

- (void)parserDidEndDictionary:(YAJLParser *)parser
{
    mapKey = nil;
    [stack removeLastObject];
}

- (void)parserDidStartArray:(YAJLParser *)parser
{
    NSString *arrayName = mapKey;
    if (mapKey == nil)
    {
        arrayName = stack.count == 0 ? @"" : [stack lastObject];
    }
    [stack addObject:(arrayName)];

    if([mapKey isEqualToString:@"something"])
    {
        // do something
    }
}

- (void)parserDidEndArray:(YAJLParser *)parser
{
    if([mapKey isEqualToString:@"some1"])
    {
        // do something
    }

    mapKey = nil;
    [stack removeLastObject];
}

- (void)parser:(YAJLParser *)parser didMapKey:(NSString *)key
{
    mapKey = key;
}

- (void)parser:(YAJLParser *)parser didAdd:(id)value
{
    if([mapKey isEqualToString:@"id"])
    {
        // do something    
    }
}
于 2013-09-23T13:37:31.557 回答
2

将数据写入文件,然后使用 NSData 的 dataWithContentsOfFile:options:error: 并指定 NSDataReadingMappedAlways 和 NSDataReadingUncached 标志。这将告诉系统使用 mmap() 来减少内存占用,而不是用内存块给文件系统缓存增加负担(这会使其速度变慢,但对 iOS 的负担要小得多)。

你可以在这里找到答案 iPad - Parsing an extra huge json - File ( between 50 and 100 mb)

于 2013-09-23T07:50:05.680 回答