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



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

在高级别:

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

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

如果有人需要这样的东西,请随时使用它。

.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];

您将能够更新您的进度视图,并在文件使用委托方法进行精细复制时收到通知。

最新更新