0

我的代码调用HTTP远程服务器的 post call 并获取JSON格式的结果,我已经提取了这个 JSON,但现在我需要将这些结果存储到 SQLite。根据我的阅读NSURLSessionDataTask是后台线程,所以我的困惑是,我应该调用 SQL 打开并在里面插入completionHandler(或)是否有任何其他最佳实践来处理这种类型的要求?

编辑 1

我更苦恼的一点是,在“completionHandler”中编写 SQLite 操作是否有效?“completionHandler”是否将被视为单独线程(正在执行 SessionDataTask)或主线程上的方法?

编辑 2

我也对 CoreData 相关的解决方案持开放态度。

任何帮助,将不胜感激。

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];
4

2 回答 2

1

可以从应用程序中的任何线程访问 SQLite DB。唯一的限制是 SQLite 不能愉快地容忍来自多个线程的同时访问(这里的“同时”适用于“事务”的持续时间,而不仅仅是调用 SQLite 方法的持续时间)。

因此,您必须以某种方式确保永远不会同时访问。一个简单的方法是始终使用同一个线程(例如,主线程)进行访问。或者您可以实现“软”协议,这样您就知道两个操作不会同时尝试使用数据库,因为它们在时间上是分开的。或者您可以在软件/操作系统中使用 Objective-C 锁或其他同步机制。

于 2014-12-11T21:07:53.430 回答
1

很多人使用FMDB作为 sqlite 的objective-c 包装器。

在 NSURLSession 的情况下,完成处理程序的块将在“委托队列”上执行(参见 NSURLSession 的 delegateQueue 属性)。

只要遵循 SQLite 线程规则,在完成处理程序中执行 SQLite 是有效的。我再次推荐 FMDB 她,因为它有帮助。请参阅使用 FMDatabaseQueue 和线程安全

所以你的例子看起来像:

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];
于 2014-12-11T17:17:10.330 回答