2017-09-14 7 views
0

私は自分のWebサービスからファイル(.json)をダウンロードしていますし、それは私が内容はローカルSQLliteデータベースへの「アンパック」する必要がありますダウンロードが終了するWHE。ファイルのダウンロードが完了し、すぐに使用できるようになる方法を教えてください。

私はNSURLConnectionがオープンメインスレッドを維持するために、別のスレッドで非同期にファイルをダウンロードすることをunderstannd。問題は、ファイルのダウンロードが開始されたときに、メインスレッドが、実行中の処理(この場合はファイルの内容をデータベースにロードしようとしている)を実行していることです。これが起こるまでに、ファイルはまだ存在しないか、または存在していますが、まだ完了していません。

はどうすればファイルのみAFTERデータベースに入力ファイルの内容は、実際に完全にダウンロードして使用する準備ができているというメソッドを実行するのですか?

-(void)downloadTheFileFrom:(NSString*)url withToken:(NSString*)token 
{ 
    NSString *conURL = [NSString stringWithFormat:@"%@/%@", apiURL, url]; 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:conURL]]; 
    [request setHTTPMethod:@"GET"]; 

    [request addValue:@"application/json" forHTTPHeaderField:(@"content-type")]; 
    [request addValue:token forHTTPHeaderField:(@"X-TOKEN")]; 
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; 

    [conn scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 

    [conn start]; 
    [self saveJsonToDatabase]; 
} 

データベースにファイルを保存する方法:NSURLConnectionため

-(void)saveJsonToDatabase 
{ 
    NSString *jsonFileToSave = @"drug.json"; 
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; 
    NSError *jsonError = nil; 

    NSString *jsonFile = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/content/formulary/files/%@", jsonFileToSave]]; 
    NSData *jsonData = [NSData dataWithContentsOfFile:jsonFile]; 
    NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonError]; 

    NSString *formularyTable = [NSString stringWithFormat:@"formulary_%@", [jsonFileToSave stringByDeletingPathExtension]]; 

    FormularyDBManager *formularyDBManagerInstance = [FormularyDBManager new]; 
    [formularyDBManagerInstance insertInto:formularyTable arrayOfDicts:jsonArray]; 
} 

デリゲートメソッド:あなたはNSURLSessionDownloadTaskを使用している場合、それは完了ですので、

-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response { 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 

    NSString *apiUrl = [NSString stringWithFormat:@"%@",[response URL]]; 
    NSArray *pathComponents = [apiUrl pathComponents]; 
    NSString *areaFolder = [pathComponents objectAtIndex:3]; 
    NSString *fileName = [response suggestedFilename]; 
    NSString *fileType = [fileName pathExtension]; 

    NSString *docsfolderPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    NSString *folderPath = [docsfolderPath stringByAppendingString:[NSString stringWithFormat:@"/content/%@/%@", areaFolder, contentType]]; 

    BOOL isDir; 
    NSFileManager *fileManager= [NSFileManager defaultManager]; 
    if(![fileManager fileExistsAtPath:folderPath isDirectory:&isDir]) 
     if(![fileManager createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:NULL]) 
      NSLog(@"FileDownloader - connection - Error: Create folder failed %@", folderPath); 

    NSString *filePath = [folderPath stringByAppendingPathComponent:fileName]; 

    [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; 
    connection.file = [NSFileHandle fileHandleForUpdatingAtPath:filePath]; 

    _currentFile = fileName; 
} 
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    [connection.file writeData:data]; 
} 
-(NSCachedURLResponse *)connection:(FileURLConnection *)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse { 
    return nil; 
} 
-(void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    [connection.file closeFile]; 
} 
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    NSLog(@"GetData - connection - error - %@", error); 
} 

答えて

1

NSURLConnectionが廃止されましたので、私はNSURLSessionとNSURLSessionDownloadTaskに固執するでしょう。 A NSURLSessionDownloadTaskがブロックまたはデリゲートに答えることができる

は、ブロックのバリアントに固執することができます。

// Your request 
NSString *conURL = [NSString stringWithFormat:@"%@/%@", apiURL, url]; 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:conURL]]; 
[request setHTTPMethod:@"GET"]; 

[request addValue:@"application/json" forHTTPHeaderField:(@"content-type")]; 
[request addValue:token forHTTPHeaderField:(@"X-TOKEN")];  

// Create a simple Session 
NSURLSession *session = [NSURLSession sharedSession]; 
// Create the downloadTask 
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable tempLocation, NSURLResponse * _Nullable response, NSError * _Nullable error) { 
    // this block will be called on a async thread when the task is finished. 
    // if no error occurred and we got a path lets store the data. 
    if (!error && tempLocation) { 
     // I pass the location to your function, so it can read the file. 
     [self saveJsonToDatabase:tempLocation]; 
    } 
}]; 
[downloadTask resume]; // don't forget to start the task. 

タスクは、ブロックが終了または失敗したときにそのブロックを呼び出します。 tempLocationのファイルは一時的なもので、後で削除されます。保存する場合は別のパスに移動する必要があります。

詳細については、あなたは私が探しているものを合うことができる。これは、それのように見えるNSURLSession + Tasks

+0

を使用するためのリンゴのドキュメントを読むことができます。ファイルを保存する場所を定義できますか?私はこのクラスを使ってたくさんのファイルを保存しています。私は「interecpt」してその内容をデータベースに入れなければなりません。 – Ryan

+0

ファイルを渡された場所に移動できます。 '[[NSFileManager defaultManager] copyItemAtPath:tempLocation toPath:passedFilePath error:nil];'このトリックを行うべきです。 – Amset

+0

コードを書き直し、提案された変更を追加した後、これは意図したとおりに動作します。また、このメソッドはデリゲートメソッドの負荷を心配するだけのことよりもはるかに簡単です。ありがとう! – Ryan

0

処理するために容易になりますブロック法。ダウンロードが完了すると、ブロック内のコードが実行されます。 Plus NSURLConnectionは廃止されました。

関連する問題