【问题标题】:Saving asynchronously downloaded files' contents to SQLITE将异步下载的文件内容保存到 SQLITE
【发布时间】:2017-10-20 09:54:52
【问题描述】:

BACKGROUND 我正在循环通过一堆 URL 来下载几个文件。下载文件后,我需要从文件中“解压”JSON,并将数据插入 SQLite 数据库。

问题 下载文件时,我尝试将文件的内容插入数据库,因为文件是异步下载的并且文件大小不同,第二个文件试图插入到在第一个文件完成之前的数据库,因此数据库被锁定以供后续文件使用。

问题如何让文件在尝试保存下一个之前等待前一个保存到数据库中?

获取文件的代码:

-(void)downloadJsonDataFrom:(NSURL *)url withToken:(NSString*)token saveTo:(NSString *)saveLocation withName:(NSString*)fileName
{
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"GET"];
    [request addValue:@"application/json" forHTTPHeaderField:(@"content-type")];
    [request addValue:token forHTTPHeaderField:(@"X-TOKEN")]; 

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:nil delegateQueue:nil];

    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse * response, NSError * error) {

    if (!error && data) {

        NSError *writeError = nil;
        BOOL writeOK = [data writeToFile:saveLocation options:NSDataWritingAtomic error:&writeError];

        if (writeOK) {
            NSLog(@"downloadTheFileFrom writeOK for %@", fileName);
           [sqlFileHandler saveJsonToSql:saveLocation];
        } else {
            NSLog(@"Error writing file : %@ %@", fileName, writeError);
        }


    } else {
        NSLog(@"downloadTheFileFrom Error : %@",error);
    }
}];
[dataTask resume];

【问题讨论】:

  • 先将所有文件写入磁盘,再写入数据库
  • @schmidt9 当我将“保存到数据库”代码移出时,它会在文件完成下载之前运行,因为文件需要几秒钟才能保存。

标签: ios objective-c cocoa-touch asynchronous


【解决方案1】:

使用来自 GCD(Grand Central Dispatch)的串行队列。一些未经测试的代码:

dispatch_queue_t serialQueue = dispatch_queue_create("com.unique.sql.queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
        [sqlFileHandler saveJsonToSql:saveLocation];
    }); 

对于那些具有这种说服力的人来说,一些更快捷的东西:

let serialQueue = DispatchQueue(label: "com.unique.sql.queue", attr: DISPATCH_QUEUE_SERIAL)
serialQueue.sync { 
    operationThatNeedsToRunSerially()
}

【讨论】:

  • 我已将 saveJsonToSql 方法调用包装在 DispatchQueue 中,但数据库仍然被锁定,尽管并非总是如此。
  • 尝试 dispatch_sync 而不是 dispatch_async。
猜你喜欢
  • 1970-01-01
  • 2013-05-05
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多