4

私のiPhoneアプリでは、デフォルトのNSFileManagerを使用して、一部のデータをコピーおよび移動しています。データ量は数MBになる場合がありますので、コピーが完了するまでに数秒かかる場合があります。ユーザーがコピープロセスを開始してアプリケーションを終了した場合、バックグラウンドモードでディスクへの書き込みを続行できますか?もしそうなら、どのように?新しいコピープロセスを開始したくありませんが、実行中のプロセスを終了するだけです。

現在、2種類のメソッド呼び出しを使用しています。

[imageData writeToFile:path atomically:YES];

[fm copyItemAtPath:sourcePath toPath:destinationPath error:&error];

両方の呼び出しは別のメソッドでラップされ、を介してバックグラウンドで実行され-performSelectorInBackground:withObject:ます。

もう1つの質問は、書き込み操作がどこまで進んだか、または少なくともすでに完了しているかどうかについての情報を取得できるかどうかです。

編集:いくつかの詳細情報:現在、私はバックグラウンドタスクをまったく実装していません。ユーザーがホームボタンを押すと、実行中のディスク操作はどうなりますか?それらは切り取られただけで、ファイルは不完全ですか?次のスタートで書き続けることはできますか?それらはキャンセルされ、不完全なファイルは削除されますか?

要約すると、私はディスクにデータを書き込んでおり、書き込み操作中にユーザーがホームボタンを押したときにデータの一貫性を維持したいと考えています。どうすればこれを達成できますか?

4

2 に答える 2

4

デフォルトでは、ユーザーがホームボタンを押してもアプリは実際には終了しません。したがって、それほど長くはかからない限り、そのタスクを完了する必要があります。時間がかかる場合は、この質問をご覧ください:タスク完了を実装する方法

1つ:performSelectorInBackground:withObject:が実際に何をするのか混乱していると思います。「 ...バックグラウンドモードでディスクへの書き込みを続行します」で使用される背景と「performSelectorInBackground : withObject:」の背景は同じ背景ではありませ

前者の背景: アプリがユーザーに表示されなくなったが、少なくともしばらくの間は実行されている場合です。(ユーザーがホームボタンを2回押して、別のアプリに変更した場合)

後者のバックグラウンド: メインスレッドの反対側にあるバックグラウンドスレッドを指します。

この場合、performSelectorInBackground:withObject:を使用するかどうかは、アプリがバックグラウンドモードで実行できるかどうかには影響しません。これらは完全に異なるものです

[fm copyItemAtPath:ToPath:error:]の直後にBOOL finish=YESを設定できます。それをNSUserDefaultsに保存し、アプリが再びフォアグラウンドになったらそのフラグを確認します;)

それが役に立てば幸い ;)

于 2011-01-03T08:54:47.447 に答える
4

調べてみてください。NSOperationQueueドキュメントページはこちらです。

また、ここここNSOperationQueueにある使用に対処する2つの既存のStackOverflowの質問があります。どちらも答えを受け入れました。

ファイルの書き込みが完了したかどうかを確認することに関しては、非常に大きなファイルを作成するOSXアプリケーションを作成しているときにもこの問題が発生しました。ユーザーが書き込みの進行状況を追跡できるようにしたかったのです。私はNSTimerと一緒に使用することになったUIProgressBar

基本的に、ファイルの(予想される)合計サイズを決定する必要があります。次に、ファイルを作成するときに、をcheckFileWritingProgress使用して定期的に呼び出すことができる別のメソッド(以下のコードにあります)が必要ですNSTimer。現在の進行状況を予想される合計ファイルサイズと照合し、UIProgressBarそれに応じて更新します。

私はあなたが始めるためにいくつかのコードを提供しました。

- (void)checkFileWritingProgress:(NSTimer *)someTimer {
    fileAttributes = [fileManager attributesOfItemAtPath:[NSString stringWithFormat:@"%@.data",saveLocation] error:nil];
    currentFileSize = [fileAttributes fileSize]; // instance variable
    if(currentFileSize < maxFileSize) { // maxFileSize is instance variable
        [progressBar setDoubleValue:(((double)currentFileSize/(double)maxFileSize)*100)];
            // progressWindows OS X only... not on iOS
        //[progressWindow setTitle:[NSString stringWithFormat:@"Writing... | %.0f%%",(((double)currentFileSize/(double)maxFileSize)*100)]];
    }
    else {
        [progressBar setDoubleValue:100.0];
    }
}

そしてタイマー...

NSTimer *timer = [[NSTimer scheduledTimerWithTimeInterval:0.01
                                                          target:self
                                                        selector:@selector(checkFileWritingProgress:)
                                                        userInfo:nil
                                                         repeats:YES] retain];

//(linked to timer... this is the 
// CORRECT way to use a determinate progress bar)

[progressBar setIndeterminate:NO];
[progressBar setDoubleValue:0.0];
[progressBar displayIfNeeded];

このコードがお役に立てば幸いです。何か明確にする必要があるかどうか教えてください。

于 2011-01-25T07:30:36.120 に答える