使用NSURLConnection返回超大字符串的正确方法是什么?

时间:2014-02-10 21:33:11

标签: ios string csv ios7 nsurlconnection

我连接的URL是一个php文件,以CSV输出的形式输出大量数据。

现在一切正常,我没有收到任何使用NSURLConnection的错误。但是,当使用connectionDidFinishLoading时,我没有收到所有数据。我将数据附加到didReceiveData中。有时我获得的数据比其他数据更多,因此连接似乎没有足够长的时间来完成获取数据。

使用NSURLConnection获取超大字符串的正确方法是什么?

以下是我正在使用的代码:

- (void)checkDatabaseUpdate_Places
{

    NSString *post =
    [[NSString alloc] initWithFormat:@"some_parameters_here"];

    NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];

    NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

    NSURL *url = [NSURL URLWithString:@"site_url_here"];
    NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
    [theRequest setHTTPMethod:@"POST"];
    [theRequest setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [theRequest setHTTPBody:postData];
    [theRequest setTimeoutInterval:30];
    [theRequest setHTTPShouldHandleCookies:NO];

    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    if( theConnection )
    {
        placesTableData = [[NSMutableData alloc] init];
        placesTableVerification = @"getting data";
    }
    else
    {
        NSLog(@"Bad Connection for Places");
    }

}

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    long long dataSize = [response expectedContentLength];
    NSLog(@"expected data size: %lld", dataSize);

    if ([placesTableVerification isEqualToString:@"getting data"]) {
        [placesTableData setLength: 0];
    }
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    if ([placesTableVerification isEqualToString:@"getting data"]) {
        [placesTableData appendData:data];
        placesTableVerification = @"got data";
    }

}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"connectionDidFailWithError %@",error.description);
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Defaults Could Not Load" message:@"There was an error loading your defaults. Make sure your device has an active internet connection." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];

}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{

    //Database Setup
    NSString *docsDir;
    NSArray *dirPaths;

    // Get the documents directory
    dirPaths = NSSearchPathForDirectoriesInDomains(
                                                   NSDocumentDirectory, NSUserDomainMask, YES);

    docsDir = dirPaths[0];

    // Build the path to the database file
    _databasePath = [[NSString alloc]
                     initWithString: [docsDir stringByAppendingPathComponent:
                                      @"database_name.db"]];

    NSLog(@"%@",_databasePath);

    NSFileManager *filemgr = [NSFileManager defaultManager];

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

        if (sqlite3_open(dbpath, &_database) == SQLITE_OK)
        {
            //do nothing
        } else {
            NSLog(@"Failed to open database");
        }
    }

    const char *dbpath = [_databasePath UTF8String];
    sqlite3_stmt    *statement;
    //start Places Table Update
    if ([placesTableVerification isEqualToString:@"got data"]) {

        NSString *returnedData = [[NSString alloc] initWithBytes: [placesTableData mutableBytes] length:[placesTableData length] encoding:NSUTF8StringEncoding];

        NSLog(@"%lu -- %@",(unsigned long)[placesTableData length],returnedData);


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

            NSArray *tempArray = [[NSArray alloc] initWithArray:[returnedData componentsSeparatedByString:@"~~"]];

            NSString *tempItems = [[NSString alloc] init];

            for (tempItems in tempArray) {

                NSArray *itemArray = [[NSArray alloc] init];
                itemArray = [tempItems componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"|"]];

                NSMutableString *loadDB = [[NSMutableString alloc] initWithFormat:@"INSERT OR REPLACE INTO PLACES (ID,NAME,TYPE,CATEGORY,LATITUDE,LONGITUDE,CHAMBER_PRIMARY_CATEGORY,CHAMBER_SECONDARY_CATEGORY,INFORMATION,PHONE,FAX,EMAIL,WEBSITE,PHYSICAL_ADDRESS,MAILING_ADDRESS,START_DATE,STOP_DATE,HOTSPOT_FACTOR,MODIFIED) VALUES ("];

                int lastIndex = [itemArray count];
                int count = 0;

                NSString *tempItem = [[NSString alloc] init];

                for (tempItem in itemArray) {
                    count++;
                    NSString* string = [NSString stringWithFormat:@"%@" , tempItem];
                    if (count != lastIndex && string.length != 0) {
                        [loadDB appendString:@"\""];
                        [loadDB appendString:tempItem];
                        [loadDB appendString:@"\""];
                        [loadDB appendString:@","];
                    }
                    else if (count == lastIndex && string.length != 0){
                        [loadDB appendString:@"\""];
                        [loadDB appendString:tempItem];
                        [loadDB appendString:@"\""];
                    }
                    else {
                        [loadDB appendString:@"\"\","];
                    }


                }
                //end for

                loadDB = [[loadDB substringWithRange:NSMakeRange(0, loadDB.length)] mutableCopy];

                [loadDB appendString:@")"];

                //NSLog(loadDB);

                const char *errMsg;

                const char *insert_stmt = [loadDB UTF8String];

                sqlite3_prepare_v2(_database, insert_stmt,
                                   -1, &statement, &errMsg);
                NSLog(@"%s",insert_stmt);
                NSLog(@"%d",sqlite3_prepare_v2(_database, insert_stmt,
                                               -1, &statement, &errMsg));
                NSLog(@"%s",sqlite3_errmsg(_database));

                if (sqlite3_step(statement) == SQLITE_DONE)
                {
                    NSLog(@"Places Table Updated");
                }
                //end if
                else {
                    NSLog(@"Places Table Failed To Update");
                    //NSLog(@"%d",sqlite3_step(statement));
                }
                //end else

                sqlite3_finalize(statement);

                NSLog(@"%s",sqlite3_errmsg(_database));

            }
            //end for

        }
        //end if

        sqlite3_close(_the_kearney_app_database);

        [startupProgress setProgress:0.3 animated:YES];

    }
    //end Places Table Update

}

任何帮助,你可以告诉我为什么我可能没有从服务器获得完整输出,这是值得赞赏的。

解决方案

- (void)checkDatabaseUpdate_Places
{

    NSString *post =
    [[NSString alloc] initWithFormat:@"some_parameters_here"];

    NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];

    NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

    NSURL *url = [NSURL URLWithString:@"site_url_here"];
    NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
    [theRequest setHTTPMethod:@"POST"];
    [theRequest setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [theRequest setHTTPBody:postData];
    [theRequest setTimeoutInterval:30];
    [theRequest setHTTPShouldHandleCookies:NO];

    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    if( theConnection )
    {
        placesTableData = [[NSMutableData alloc] init];
        placesTableVerification = @"getting data";
    }
    else
    {
        NSLog(@"Bad Connection for Places");
    }

}

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    long long dataSize = [response expectedContentLength];
    NSLog(@"expected data size: %lld", dataSize);

    if ([placesTableVerification isEqualToString:@"getting data"]) {
        [placesTableData setLength: 0];
    }
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    if ([placesTableVerification isEqualToString:@"getting data"]) {
        [placesTableData appendData:data];
    }

}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"connectionDidFailWithError %@",error.description);
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Defaults Could Not Load" message:@"There was an error loading your defaults. Make sure your device has an active internet connection." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];

}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{

    //Database Setup
    NSString *docsDir;
    NSArray *dirPaths;

    // Get the documents directory
    dirPaths = NSSearchPathForDirectoriesInDomains(
                                                   NSDocumentDirectory, NSUserDomainMask, YES);

    docsDir = dirPaths[0];

    // Build the path to the database file
    _databasePath = [[NSString alloc]
                     initWithString: [docsDir stringByAppendingPathComponent:
                                      @"database_name.db"]];

    NSLog(@"%@",_databasePath);

    NSFileManager *filemgr = [NSFileManager defaultManager];

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

        if (sqlite3_open(dbpath, &_database) == SQLITE_OK)
        {
            //do nothing
        } else {
            NSLog(@"Failed to open database");
        }
    }

    const char *dbpath = [_databasePath UTF8String];
    sqlite3_stmt    *statement;
    //start Places Table Update
    if ([placesTableVerification isEqualToString:@"getting data"]) {

        NSString *returnedData = [[NSString alloc] initWithBytes: [placesTableData mutableBytes] length:[placesTableData length] encoding:NSUTF8StringEncoding];

        NSLog(@"%lu -- %@",(unsigned long)[placesTableData length],returnedData);


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

            NSArray *tempArray = [[NSArray alloc] initWithArray:[returnedData componentsSeparatedByString:@"~~"]];

            NSString *tempItems = [[NSString alloc] init];

            for (tempItems in tempArray) {

                NSArray *itemArray = [[NSArray alloc] init];
                itemArray = [tempItems componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"|"]];

                NSMutableString *loadDB = [[NSMutableString alloc] initWithFormat:@"INSERT OR REPLACE INTO PLACES (ID,NAME,TYPE,CATEGORY,LATITUDE,LONGITUDE,CHAMBER_PRIMARY_CATEGORY,CHAMBER_SECONDARY_CATEGORY,INFORMATION,PHONE,FAX,EMAIL,WEBSITE,PHYSICAL_ADDRESS,MAILING_ADDRESS,START_DATE,STOP_DATE,HOTSPOT_FACTOR,MODIFIED) VALUES ("];

                int lastIndex = [itemArray count];
                int count = 0;

                NSString *tempItem = [[NSString alloc] init];

                for (tempItem in itemArray) {
                    count++;
                    NSString* string = [NSString stringWithFormat:@"%@" , tempItem];
                    if (count != lastIndex && string.length != 0) {
                        [loadDB appendString:@"\""];
                        [loadDB appendString:tempItem];
                        [loadDB appendString:@"\""];
                        [loadDB appendString:@","];
                    }
                    else if (count == lastIndex && string.length != 0){
                        [loadDB appendString:@"\""];
                        [loadDB appendString:tempItem];
                        [loadDB appendString:@"\""];
                    }
                    else {
                        [loadDB appendString:@"\"\","];
                    }


                }
                //end for

                loadDB = [[loadDB substringWithRange:NSMakeRange(0, loadDB.length)] mutableCopy];

                [loadDB appendString:@")"];

                //NSLog(loadDB);

                const char *errMsg;

                const char *insert_stmt = [loadDB UTF8String];

                sqlite3_prepare_v2(_database, insert_stmt,
                                   -1, &statement, &errMsg);
                NSLog(@"%s",insert_stmt);
                NSLog(@"%d",sqlite3_prepare_v2(_database, insert_stmt,
                                               -1, &statement, &errMsg));
                NSLog(@"%s",sqlite3_errmsg(_database));

                if (sqlite3_step(statement) == SQLITE_DONE)
                {
                    NSLog(@"Places Table Updated");
                }
                //end if
                else {
                    NSLog(@"Places Table Failed To Update");
                    //NSLog(@"%d",sqlite3_step(statement));
                }
                //end else

                sqlite3_finalize(statement);

                NSLog(@"%s",sqlite3_errmsg(_database));

            }
            //end for

        }
        //end if

        sqlite3_close(_the_kearney_app_database);

        [startupProgress setProgress:0.3 animated:YES];

    }
    //end Places Table Update

}

1 个答案:

答案 0 :(得分:4)

使用长数据,您可以获得多个didReceiveData:回调。所以你必须追加所有这些,而不是在第一个之后停止。

来自documentation

  

委托应该连接内容   传递的每个数据对象,以构建URL的完整数据   负荷。