【问题标题】:NSFileManager: Continue writing to disk in background?NSFileManager:继续在后台写入磁盘?
【发布时间】:2023-03-22 17:28:01
【问题描述】:

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

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

[imageData writeToFile:path atomically:YES];

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

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

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

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

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

【问题讨论】:

    标签: iphone multithreading cocoa-touch background nsfilemanager


    【解决方案1】:

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

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

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

    后一种背景: 指后台线程,与主线程相反。

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

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

    希望对你有帮助;)

    【讨论】:

    • Backgorund 在任何一种情况下对我来说都是绝对清楚的。 ;) 我刚刚添加了完整的信息。这可能对我后一个关于进展的问题很重要。设置一个 BOOL 并不能真正解决我的问题,因为一次可能有多个磁盘操作。
    • @Björn 使用 int 而不是 BOOL 来计算未完成的操作?
    • 阅读这个:developer.apple.com/library/ios/#documentation/iPhone/… 它说系统最多会给你 30 秒的生命;)请参阅:beginBackgroundTaskWithExpirationHandler: 方法从这里开始:developer.apple.com/library/ios/#documentation/UIKit/Reference/… 在过期处理程序中我会检查:什么 %被复制了? 100% 80%。
    • 在 30 秒内,您可以写入数百 MB(如果不是更多)...那时间对您来说应该足够了 ;)
    【解决方案2】:

    您可能想查看NSOperationQueue,文档页面是here

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

    至于确定文件写入是否完成,我在编写一个创建非常大文件的 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];
    

    我希望这段代码有所帮助。如果有什么需要澄清的,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-02
      • 2011-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多