7

iOSアプリを書いています。私のアプリでは、いくつかのファイルをあるフォルダーから別のフォルダーにコピーしたいと思います。ただし、ファイルによっては大きすぎるため、コピーが完了するまでに長い時間がかかります。そこで、コピーのパーセンテージを表示するプログレスバーを追加したいと思います。しかし、ファイルマネージャーにはパーセンテージを取得するためのコールバックメソッドがないことがわかりました。誰かがそれに対する良い解決策を持っていますか?

4

2 に答える 2

9

高レベル:

  1. 別のスレッド (T1) でコピー プロセスを実行します。
  2. 定期的に (たとえば 100 ミリ秒ごとに) 宛先ファイルを読み取る別のスレッド (T2) を実行しますcurrent_size
  3. パーセンテージを計算します :current_size / total_size
  4. プログレスバーの UI 要素を更新する
于 2012-05-02T13:35:58.707 に答える
3

@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

彼ら

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

また、進行状況ビューを更新し、デリゲート メソッドを使用してファイルのコピーが完了したときに通知を受け取ることができます。

于 2016-02-24T18:27:15.660 に答える