Question

I have three methods that I want them to execute like follows:

+(void)method1{
    // Some code
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i=0; i<count; i++) {
            //getting object(x) from json
            [self method2:x];//trigger method2
        }
    });
}

+(void)method2:(NSString*)x{
// Some code
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i=0; i<count; i++) {
            //getting objects(y,z) from json
            //SAVE that object in SQLite database
            [self method3:y:z];//trigger method3
        }
    });
}

+(void)method3:(NSString*)y :(NSString*)z{
// Some code
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for (int i=0; i<count; i++) {
            //getting object from json
            //SAVE that object in SQLite database
        }
    });
}

What i have is always a random data in database, plus, not all data is stored. My question is how to organize those async tasks to get the right data in database. Thank you very much for your help.

EDIT:

+(void)getData:(NSString*)artist{

    LKDBHelper* globalHelper = [LKDBHelper getUsingLKDBHelper];

    NSMutableArray *arrayOfSongs=[[NSMutableArray alloc]init];
    artist = [artist stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    //DLog(@"artisttt %@",artist);

    NSString *url=[NSString stringWithFormat:@"%@?artist=%@", @"http://localhost/kalimat/get_kalimat.php",artist];

    url = [url stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];

    //NSLog(@"url %@",url);

    NSURL *urlChannels= [ NSURL URLWithString:url];


    NSURLRequest *request = [NSURLRequest requestWithURL:urlChannels];

    [LKDBHelper clearTableData:[Song class]];

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSMutableArray *arrayOfJson=JSON;


            for (int i=0; i<[arrayOfJson count]; i++) {
                //DLog(@"artist songs loop");

                NSMutableDictionary *songDico=[arrayOfJson objectAtIndex:i];

                DCKeyValueObjectMapping *parser = [DCKeyValueObjectMapping mapperForClass: [Song class]];

                Song *song = [parser parseDictionary:songDico];
                song.artist=artist;




                [globalHelper insertToDB:song];

                [self getLyricsWhereArtist:artist andSong:song.song];
            }



        });

    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response,
                NSError *error, id JSON) {
        DLog(@"Request Failure Because %@",[error userInfo]);
    }];


    [operation start];

}
Was it helpful?

Solution

If you have multiple threads updating a database, you can create a dedicated serial queue for your SQLite interaction and dispatch all database interaction to that single queue. That way, even though you have multiple threads performing network operations, you can dispatch all database updates to this new dedicated queue, and it will completely eliminate all database contention issues. You're probably having database updates fail because you have multiple threads trying to update the same database and some of them are likely failing.

The fact that you suspect might have database updates silently failing is worrying. Are you possibly not checking the return codes of all of your SQLite calls? It really is critical to check the return code every SQLite call, and if it failed, look at sqlite3_errmsg (or if using FMDB, lastErrorMessage). If you don't do this, you're just flying blind. You're fortunate at this point that the problem was obvious, but next time the problem may be more subtle, and you'll pull your hair tracking down the issue.

Finally, since you're already using AFNetworking, I'd also suggest that you consider using AFHTTPRequestManager. Specifically, rather than building the URL yourself, use the GET method, passing the params dictionary. Your stringByAddingPercentEncodingWithAllowedCharacters code will generally work, but may fail in certain scenarios (notably, the unlikely scenario that your parameter value contained a + or & in it). Furthermore, if you use GET and set the request manager's operationQueue.maxConcurrentOperationCount to something reasonable, e.g. 4, you'll also eliminate the possibility of requests timing out unnecessarily on slow connections. Bottom line, there are a couple of subtle networking issues that AFHTTPRequestManager will handle, but your current implementation won't.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top