我的代码调用HTTP
调用远程服务器并获得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];
答案 0 :(得分:1)
很多人使用FMDB作为sqlite的客观包装。
在NSURLSession的情况下,完成处理程序的块将在"委托队列"上执行。 (请参阅NSURLSession的delegateQueue属性)。
只要遵循SQLite线程规则,在完成处理程序中执行SQLite是有效的。我再次推荐FMDB,因为它有帮助。请参阅Using FMDatabaseQueue and Thread Safety。
所以你的例子看起来像:
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];
答案 1 :(得分:1)
可以从应用程序中的任何线程访问SQLite DB。唯一的限制是SQLite不能很好地容忍来自多个线程的同时访问(并且"同时"这里适用于"事务的持续时间",而不仅仅是调用SQLite的持续时间方法)。
所以你必须以某种方式确保永远不会同时访问。一种简单的方法是始终使用相同的线程(例如,主线程)进行访问。或者你可以实现" soft"协议,以便您知道两个操作不同时尝试使用数据库,因为它们在时间上是分开的。或者您可以在软件/操作系统中使用Objective-C锁或其他同步机制。