NSFileManager:继续在后台写入磁盘?

时间:2011-01-03 08:26:53

标签: iphone multithreading cocoa-touch background nsfilemanager

在我的iPhone应用程序中,我使用默认的NSFileManager来复制和移动一些数据。数据量可能是几MB,因此完成复制可能需要几秒钟。如果用户现在启动复制过程并退出应用程序,是否可以继续以后台模式写入磁盘?如果是这样,怎么样?我不想开始新的复制过程,但只完成正在运行的过程。

我目前正在使用两种方法调用:

[imageData writeToFile:path atomically:YES];

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

两个调用都包含在另一个方法中,并通过-performSelectorInBackground:withObject:在后​​台执行。

另一个问题是,我是否可以获得有关写入操作进展程度的信息,或者至少是否已经完成?

编辑:更多信息: 目前,我根本没有执行任何后台任务。当用户按下主页按钮时,运行磁盘操作会发生什么?他们刚刚被切断,文件是不完整的?我可以在下次开始时继续写作吗?它们被取消并且删除了不完整的文件吗?

总结一下:我正在将数据写入磁盘,并且当用户在写入操作期间按下主页按钮时,我希望它保持一致。我该如何实现这一目标?

2 个答案:

答案 0 :(得分:4)

默认情况下,当用户按下主页按钮时,应用程序无法完成。因此它应该完成那项任务,只要不花太长时间。如果需要很长时间,请查看以下问题:How to implement Task completion

有一件事:我认为你对performSelectorInBackground:withObject:确实存在困惑。 后台用于“...我继续以 后台 模式写入磁盘”和后台中的“ performSelectorIn 背景 :withObject:“背景不一样

前一个背景: 当你的应用程序对用户不可见但仍在运行时,至少会持续一段时间。 (当用户按两次主页按钮并切换到另一个应用程序时)

后一种背景: 引用后台线程,它与主线程相反。

在这种情况下,如果您使用或不使用performSelectorInBackground:withObject:它将不会影响您的应用程序是否可以执行后台模式。这些是完全不同的东西

你可以在[fm copyItemAtPath:ToPath:error:]之后立即设置BOOL finished = YES;并将其保存在NSUserDefaults中并在应用程序再次到达前台时检查该标志;)

希望它有所帮助;)

答案 1 :(得分:4)

您可能需要查看NSOperationQueue,文档页面为here

此外,还有两个现有的Stack Overflow问题使用herehere NSOperationQueue来解决。两人都接受了答案。

至于确定文件写入是否已完成,我在写一个创建一个非常大的文件的OS X应用程序时也遇到了这个问题。我希望用户能够跟踪写入的进度。我最终使用NSTimerUIProgressBar

基本上,您需要确定文件的(预期)总大小。然后,当您编写文件时,您应该使用另一种方法(在下面的代码中我有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];

我希望此代码有所帮助。如果有任何事情需要澄清,请告诉我。