Search code examples
objective-cjsonios7sqlitensurlsessiondatatask

Store NSURLSessionDataTask response to SQLite database?


My code calls HTTP post call to remote server and obtains results in JSON format, I have extracted this JSON, but now I need to store these results to SQLite. Based on my reading NSURLSessionDataTask is background thread, so my confusion is, should I call SQL open and insert inside completionHandler (or) is there any other best practice to handle this type of requirements?

EDIT 1

The point I am struggling more is, is it valid to write SQLite operations inside "completionHandler"? does "completionHandler" will be considered as method on separate thread (which is executing SessionDataTask) or main thread?

EDIT 2

I am open to CoreData related solutions too.

Any help would be appreciated.

NSURL *loginUrl = [NSURL URLWithString:@"myurl"];
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:loginUrl];
request.HTTPMethod = @"POST";
NSString *ipData = [NSString stringWithFormat:@"uName=%@&pwd=%@",self.userName.text,self.userPwd.text];
request.HTTPBody = [ipData dataUsingEncoding:NSUTF8StringEncoding];


NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *jsonError) {
    NSLog(@"Inside post data task......");

    NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *)response;
    if(httpResp.statusCode == 200)
    {
        NSLog(@"Response succesfull.........");
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];

        if(!jsonError)
        {
            //No Json error
            NSString *uName = jsonDict[@"userName"];
            NSString *uID = jsonDict[@"uID"];
            //HOW CAN I INSERT THESE DETAILS TO SQLITE DB BEFORE CALLING SEGUE TO MOVE TO NEXT SCREEN?
            dispatch_async(dispatch_get_main_queue(), ^{
                  [self performSegueWithIdentifier:@"mysegueID" sender:self];
                });
            }
    }else
    {
        NSLog(@"Response is not succesfulll...");
    }
}];

[postDataTask resume];

Solution

  • A lot of people use FMDB as objective-c wrapper around sqlite.

    In case of NSURLSession, the block of the completion handler will be executed on the "delegate queue" (see delegateQueue property of NSURLSession).

    It is valid to do SQLite in completion handler as long as you follow SQLite threading rules. I recommend FMDB her again because it has helpers for this. See Using FMDatabaseQueue and Thread Safety.

    So your example would look like:

    FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
    
    NSURL *loginUrl = [NSURL URLWithString:@"myurl"];
    NSURLSession *session = [NSURLSession sharedSession];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:loginUrl];
    request.HTTPMethod = @"POST";
    NSString *ipData = [NSString stringWithFormat:@"uName=%@&pwd=%@",self.userName.text,self.userPwd.text];
    request.HTTPBody = [ipData dataUsingEncoding:NSUTF8StringEncoding];
    
    
    NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *jsonError) {
        NSLog(@"Inside post data task......");
    
        NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *)response;
        if(httpResp.statusCode == 200)
        {
            NSLog(@"Response succesfull.........");
            NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
    
            if(!jsonError)
            {
                //No Json error
                NSString *uName = jsonDict[@"userName"];
                NSString *uID = jsonDict[@"uID"];
                //HOW CAN I INSERT THESE DETAILS TO SQLITE DB BEFORE CALLING SEGUE TO MOVE TO NEXT SCREEN?
                [queue inDatabase:^(FMDatabase *db) {
                      NSDictionary *argsDict = @{ @"uName" : uName, @"uID" : uID};
                      [db executeUpdate:@"INSERT INTO myTable (name) VALUES (:name)" withParameterDictionary:argsDict];
                }];
    
                dispatch_async(dispatch_get_main_queue(), ^{
                      [self performSegueWithIdentifier:@"mysegueID" sender:self];
                    });
                }
        }
        else
        {
            NSLog(@"Response is not succesfulll...");
        }
    }];
    
    [postDataTask resume];