如何确定调用moveItemAtURL时需要多长时间:toURL:或replaceItemAtURL:WithItemAtURL:

Jos*_*osh 1 iphone xcode cocoa objective-c nsfilemanager

将文件从一个地方移动到另一个地方,或者在替换文件时,我总是使用这些方法moveItemAtURL:toURL:replaceItemAtURL:WithItemAtURL: 来自NSFileManager.

在调用这些方法时,我想确定需要多长时间,以便我可以使用它NSProgressIndicator来告诉用户需要多长时间.就像使用OSX移动文件时一样,它会告诉您剩余的时间.

我查看了苹果文档,但未找到任何有关此信息.想知道是否可以实施,请告知.

aLe*_*ion 5

你不能提前知道它会花多长时间.您可以做的是在复制文件时计算"完成百分比".但要做到这一点,您需要使用较低级别的API.您可以使用NSFileManagers attributesOfItemAtPath:error获取文件大小和NSStreams来进行复制(有很多方法可以做到这一点).完成百分比是bytesWritten / totalBytesInFile.

---编辑:在NSURL上添加示例代码作为类别,回调块传递写入的总字节数,百分比完成和估计剩余时间(以秒为单位).

#import <mach/mach_time.h>

@interface NSURL(CopyWithProgress)<NSObject>
- (void) copyFileURLToURL:(NSURL*)destURL withProgressBlock:(void(^)(double, double, double))block;
@end

@implementation NSURL(CopyWithProgress)

- (void) copyFileURLToURL:(NSURL*)destURL
        withProgressBlock:(void(^)(double, double, double))block
{
    ///
    // NOTE: error handling has been left out in favor of simplicity
    //       real production code should obviously handle errors.
    NSUInteger fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:self.path error:nil].fileSize;

    NSInputStream  *fileInput  = [NSInputStream inputStreamWithURL:self];
    NSOutputStream *copyOutput = [NSOutputStream outputStreamWithURL:destURL append:NO];

    static size_t bufferSize = 4096;
    uint8_t *buffer = malloc(bufferSize);
    size_t   bytesToWrite;
    size_t   bytesWritten;
    size_t   copySize = 0;
    size_t   counter  = 0;

    [fileInput open];
    [copyOutput open];

    uint64_t time0 = mach_absolute_time();

    while (fileInput.hasBytesAvailable) {
        do {
            bytesToWrite = [fileInput read:buffer maxLength:bufferSize];
            bytesWritten = [copyOutput write:buffer maxLength:bytesToWrite];
            bytesToWrite -= bytesWritten;
            copySize     += bytesWritten;
            if (bytesToWrite > 0)
                memmove(buffer, buffer + bytesWritten, bytesToWrite);
        }
        while (bytesToWrite > 0);

        if (block != nil && ++counter % 10 == 0) {
            double percent  = (double)copySize / fileSize;
            uint64_t time1  = mach_absolute_time();
            double elapsed  = (double)(time1 - time0)/NSEC_PER_SEC;
            double estTimeLeft = ((1 - percent) / percent) * elapsed;
            block(copySize, percent, estTimeLeft);
        }
    }

    if (block != nil)
        block(copySize, 1, 0);
}

@end


int main (int argc, const char * argv[])
{
    @autoreleasepool {

        NSURL *fileURL = [NSURL URLWithString:@"file:///Users/eric/bin/data/english-words.txt"];
        NSURL *destURL = [NSURL URLWithString:@"file:///Users/eric/Desktop/english-words.txt"];

        [fileURL copyFileURLToURL:destURL withProgressBlock:^(double bytes, double pct, double estSecs) {
            NSLog(@"Bytes=%f, Pct=%f, time left:%f s",bytes,pct,estSecs);
        }];
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

样本输出:

Bytes=40960.000000, Pct=0.183890, time left:0.000753 s
Bytes=81920.000000, Pct=0.367780, time left:0.004336 s
Bytes=122880.000000, Pct=0.551670, time left:0.002672 s
Bytes=163840.000000, Pct=0.735560, time left:0.001396 s
Bytes=204800.000000, Pct=0.919449, time left:0.000391 s
Bytes=222742.000000, Pct=1.000000, time left:0.000000 s
Run Code Online (Sandbox Code Playgroud)