【问题标题】:How can i parse very long JSon string in iOS without memory error?如何在没有内存错误的情况下解析 iOS 中很长的 JSon 字符串?
【发布时间】:2013-05-08 14:29:18
【问题描述】:

我是 iOS 新手,我有网络服务,我正在尝试下载 9000 多个产品信息,我有一个很长的 JSON 字符串,所以我在产品下载时收到此错误消息,

malloc: * mmap(size=1978368) 失败(错误代码=12) 错误:无法分配区域 ** 在 malloc_error_break 中设置断点进行调试

我尝试下载 1000 个以下的产品信息,并且运行良好。我想,这是内存问题。

此代码是我项目的一部分。

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{

if (temp!=nil && ![temp isEqual:@""]) {
    //basliklar arrayine ilgili tek haberin basligini aktariyoruz.
    //NSLog(@"TEMP=%@",temp);


    NSData *data = [NSJSONSerialization JSONObjectWithData:[temp dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];



    UrunAdi=[data valueForKey:@"UrunAdi"];
    UrunNo=[data valueForKey:@"UrunNo"];
    Koleksiyon=[data valueForKey:@"Koleksiyon"];
    Kompozisyon=[data valueForKey:@"Kompozisyon"];
    GrM=[data valueForKey:@"GrM"];
    URMID=[data valueForKey:@"URMID"];
    En=[data valueForKey:@"En"];
    IslemTipi=[data valueForKey:@"IslemTipi"];
    Dizim=[data valueForKey:@"Dizim"];
    KarteleKodu=[data valueForKey:@"KarteleKodu"];
    Siklik=[data valueForKey:@"Siklik"];
    Euro=[data valueForKey:@"Euro"];
    Dolar=[data valueForKey:@"Dolar"];
    Sterlin=[data valueForKey:@"Sterlin"];
    TL=[data valueForKey:@"TL"];

    [sharedManager  getNewDBConnection];

    if(![temp isEqualToString:@"false"]){

        sqlite3 *contactDB;


        NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *docsDir = [dirPaths objectAtIndex:0];
        NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: SQL]];

        NSFileManager *filemgr = [NSFileManager defaultManager];

        if ([filemgr fileExistsAtPath: databasePath ] == YES)
        {
            const char *dbpath = [databasePath UTF8String];

            if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
            {


                NSString *deleteSQL = [NSString stringWithFormat: @"delete from tblKumasBilgi"];

                const char *sql_stmt = [deleteSQL UTF8String];

                if(sqlite3_exec(contactDB, sql_stmt, NULL, NULL, NULL) == SQLITE_OK)
                {
                   // NSLog (@"Delete UserData Succesful");
                }
                else
                {
                    NSLog(@"Delete UserData Fail");
                }
                //sqlite3_close(contactDB);
            }
            else
            {
                NSLog(@"Failed to open database");
            }
        }
    }


    if([temp isEqualToString:@"false"]){

         [SVProgressHUD dismiss];

        NSString *warning = NSLocalizedString(@"Warning",nil);
        NSString *check=NSLocalizedString(@"Check Your User Info",nil);
        NSString *okay=NSLocalizedString(@"Ok", nil);

        UIAlertView *alertViewUser = [[UIAlertView alloc] initWithTitle:warning
                                                            message:check
                                                           delegate:self
                                                  cancelButtonTitle:okay
                                                  otherButtonTitles:nil, nil];

        [alertViewUser show];
        alertViewUser.tag=1;
        flag=NO;

    }
    else{

                sqlite3 *contactDB;

                NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
                NSString *docsDir = [dirPaths objectAtIndex:0];
                NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: SQL]];

                NSFileManager *filemgr = [NSFileManager defaultManager];

    if ([filemgr fileExistsAtPath: databasePath ] == YES)
    {
        const char *dbpath = [databasePath UTF8String];

        if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
        {


            for (int i = 0; i < [UrunNo count]; i++) {



                NSString *insertSQL = [NSString stringWithFormat: @"INSERT INTO tblKumasBilgi (UrunAdi,UrunNo,Koleksiyon,Kompozisyon,Grm,URMID,En,IslemTipi,Dizim,KarteleKodu,Siklik,Euro,Dolar,Sterlin,TL) VALUES ('%@','%@','%@','%@','%@','%@','%@','%@','%@','%@','%@','%@','%@','%@','%@')", [UrunAdi objectAtIndex:i], [UrunNo objectAtIndex:i], [Koleksiyon objectAtIndex:i], [Kompozisyon objectAtIndex:i], [GrM objectAtIndex:i], [URMID objectAtIndex:i], [En objectAtIndex:i], [IslemTipi objectAtIndex:i],[Dizim objectAtIndex:i],[KarteleKodu objectAtIndex:i], [Siklik objectAtIndex:i],[Euro objectAtIndex:i],[Dolar objectAtIndex:i],[Sterlin objectAtIndex:i], [TL objectAtIndex:i]];

                //NSLog(@"insert =%@",insertSQL);

            const char *sql_stmt = [insertSQL UTF8String];

            if(sqlite3_exec(contactDB, sql_stmt, NULL, NULL, NULL) == SQLITE_OK)
            {
                //NSLog (@"INSERT INTO UserData Succesful");
            }
            else
            {
                NSLog(@"INSERT INTO UserData Fail");
            }

        }
        }
        else
        {
            NSLog(@"Failed to open database");
        }
        //sqlite3_close(contactDB);
    }

        [SVProgressHUD dismiss];
        NSString *warning = NSLocalizedString(@"Warning", nil);
        NSString *dataSuccesful=NSLocalizedString(@"Data Download Succesfully", nil);
        NSString *okay=NSLocalizedString(@"Ok", nil);


        UIAlertView *alertViewDownload = [[UIAlertView alloc] initWithTitle:warning
                                                            message:dataSuccesful
                                                           delegate:self
                                                  cancelButtonTitle:okay
                                                  otherButtonTitles:nil, nil];

        [alertViewDownload show];
        alertViewDownload.tag=2;


        flag=NO;
}


tempElement=@"";

} }

感谢您的关注,我很抱歉我的英语不好。

最好的问候。

【问题讨论】:

  • 您应该尝试修改您的网络服务。这并不像你需要所有的信息仪式。在需要时分批获取产品。
  • 拜托! - 如果您可以控制网络服务,请不要一次下载 9000 多个产品。使用一些分页机制来获取每个请求的部分集合。
  • 仅包含相关代码。它在哪一行代码失败? data 不应该是NSDictionary 吗?您的 JSON 数据有多少字节?计数并没有提供太多关于大小的信息。
  • 我在这里遇到了异常,-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ if([tempElement isEqualToString:@"string"]){ temp=[temp stringByAppendingString:string]; //NSLog(@"temp = %@",temp); } }字符串内存不足我猜对吧?
  • 我将尝试分页机制,我将从 webservice 获得 1000 x 1000 的产品信息。感谢您的建议和兴趣

标签: ios objective-c memory-management memory-leaks


【解决方案1】:

不要一次下载这么多,或者,如果必须,下载 JSON 并将其保存到磁盘。然后使用为您提供解析器的 JSON 库(如 this one)并分段解析 JSON。

【讨论】:

    猜你喜欢
    • 2019-05-03
    • 2023-03-10
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    • 2012-03-23
    • 2019-11-16
    • 1970-01-01
    相关资源
    最近更新 更多