如何显示在iOS中复制大文件的进度?

我正在写一个iOS应用程序。 在我的应用程序中,我想从一个文件夹复制一些文件到另一个。 但是由于某些文件太大,完成复制需要很长时间。 所以我想添加一个进度条来显示副本的百分比。 但是我发现文件pipe理器没有callback方法来获取百分比。 有没有人有很好的解决办法呢?

在高层次:

  1. 在单独的线程(T1)中运行复制过程
  2. 运行另一个线程(T2),定期读取(比如每100ms)读取目标文件current_size
  3. 计算百分比: current_size / total_size
  4. 更新你的进度条UI元素

我用@giorashc方法创build了一个简单的类。

如果有人需要这样的东西,可以随意使用它。

.h

 #import <UIKit/UIKit.h> @protocol IDCopyUtilsDelegate; @interface IDCopyUtils : NSObject @property (nonatomic, weak) id<IDCopyUtilsDelegate> delegate; - (void)copyFileAtPath:(NSString *)sourcePath toPath:(NSString *)targetPath; @end // 3. Definition of the delegate's interface @protocol IDCopyUtilsDelegate <NSObject> - (void)setCopyProgress:(float)progress; - (void)didFinishedCopyWithError:(NSError *)error; @end 

.m

 #import "IDCopyUtils.h" @interface IDCopyUtils() @property (nonatomic, strong) NSTimer *timer; @property (nonatomic, strong) NSString *sourcePath; @property (nonatomic, strong) NSString *targetPath; @end @implementation IDCopyUtils - (void)copyFileAtPath:(NSString *)sourcePath toPath:(NSString *)targetPath { self.sourcePath = sourcePath; self.targetPath = targetPath; NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error; if ([fileManager fileExistsAtPath:self.targetPath] == YES) { [fileManager removeItemAtPath:self.targetPath error:&error]; } self.timer = [NSTimer scheduledTimerWithTimeInterval:0.100 target:self selector:@selector(checkFileSize) userInfo:nil repeats:YES]; [self performSelector:@selector(startCopy) withObject:nil afterDelay:0.5]; } - (void)checkFileSize { dispatch_async(dispatch_get_main_queue(), ^{ NSDictionary *attributesSource = [[NSFileManager defaultManager] attributesOfItemAtPath:self.sourcePath error:NULL]; unsigned long long fileSize = [attributesSource fileSize]; NSDictionary *attributesTarget = [[NSFileManager defaultManager] attributesOfItemAtPath:self.targetPath error:NULL]; unsigned long long fileSizeTarget = [attributesTarget fileSize]; double progress = (float)fileSizeTarget / (float)fileSize; if (self.delegate && [self.delegate respondsToSelector:@selector(setCopyProgress:)]) { [self.delegate setCopyProgress:progress]; } NSLog(@"Size: %f", progress); }); } - (void)startCopy { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error; if ([fileManager fileExistsAtPath:self.targetPath] == YES) { [fileManager removeItemAtPath:self.targetPath error:&error]; } if ([fileManager fileExistsAtPath:self.targetPath] == NO) { [fileManager copyItemAtPath:self.sourcePath toPath:self.targetPath error:&error]; [self.timer invalidate]; self.timer = nil; if (self.delegate && [self.delegate respondsToSelector:@selector(didFinishedCopyWithError:)]) { [self.delegate didFinishedCopyWithError:error]; } } }); } @end 

你可以像这样使用它(例如):

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"iso"]; NSString *targetPath = [documentsDirectory stringByAppendingPathComponent:@"test.iso"]; IDCopyUtils *copyUtils = [[IDCopyUtils alloc] init]; copyUtils.delegate = self; [copyUtils copyFileAtPath:sourcePath toPath:targetPath]; 

而且我们可以更新进度视图,并在文件使用委托方法完成复制时得到通知。