4

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

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

[imageData writeToFile:path atomically:YES];

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

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

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

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

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

4

2 回答 2

4

你可能想看看NSOperationQueue,文档页面在这里

还有两个现有的 Stack Overflow 问题可以解决使用的问题,这里NSOperationQueue这里这里。两者都接受了答案。

至于确定文件写入是否已完成,我在编写创建一个非常大的文件的 OS X 应用程序时也遇到了这个问题。我希望用户能够跟踪写入的进度。我最终使用了一个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 回答
4

默认情况下,当用户按下主页按钮时,您的应用程序并没有真正完成。因此,只要不需要太长时间,它就应该完成该任务。如果需要很长时间,请看一下这个问题:如何实现任务完成

一件事:我认为您对 performSelectorInBackground:withObject: 的真正作用感到困惑。“...我继续以后台模式写入磁盘”中使用的背景和“performSelectorIn Background :withObject:”中的背景不是同一个背景

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

后者后台: 指后台线程,与主线程相反。

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

您可以在 [fm copyItemAtPath:ToPath:error:]; 之后设置 BOOL finished = YES 并将其保存在 NSUserDefaults 中,并在您的应用再次进入前台时检查该标志;)

希望能帮助到你 ;)

于 2011-01-03T08:54:47.447 回答