2011年7月8日金曜日

Cocoa ファイルの非同期コピー(9)

ひとつのファイルを非同期コピーするクラスを書く。ざっとこんな感じ。コメントはもともとのソースにあったもの。おおもとのソースは

Cocoa Tutorial: File Copy With Progress Indicator

のはず。

#import "FileAsyncCopyer.h"


@implementation FileAsyncCopyer
@synthesize complateCopyBytes,isCopyDone;
-(id)initWithSorceURL:(NSURL*)sURL destURL:(NSURL*) dURL{
    self=[super init];
    if(self){
        sourceURL=[sURL retain];
        distURL=[dURL retain];
        isCopyDone=NO;
       
    }
    return self;
}

- (void) controlCopyingState:(FSFileOperationRef) fileOp
          FileOperationStage: (FSFileOperationStage) stage
                      Status:(OSStatus) error
               DictionaryRef:(CFDictionaryRef)statusDictionary
{
    
    if (error != noErr){
       
    }
    
 if (statusDictionary)
    {
      
  CFNumberRef bytesCompleted;
  bytesCompleted = (CFNumberRef) CFDictionaryGetValue(statusDictionary, kFSOperationBytesCompleteKey);
 
 
  CFNumberGetValue (bytesCompleted, kCFNumberMaxType, &complateCopyBytes);
       
        NSLog(@"コピー済み:%@ %f Bytes",[sourceURL path] ,complateCopyBytes);
    }
 
 if (stage == kFSOperationStageComplete) {
        NSLog(@"コピー完了 %@",[sourceURL path]);
        isCopyDone=YES;
    }
}

static void statusCallback (FSFileOperationRef fileOp,
                            const FSRef *currentItem,
                            FSFileOperationStage stage,
                            OSStatus error,
                            CFDictionaryRef statusDictionary,
                            void *info )
{
    FileAsyncCopyer* entry=(FileAsyncCopyer *)info;
    [entry controlCopyingState: fileOp FileOperationStage: stage Status: error DictionaryRef: statusDictionary];
    
}

-(void)startCopyAsync{
    CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    FSFileOperationRef fileOp = FSFileOperationCreate(kCFAllocatorDefault);
    
    OSStatus status = FSFileOperationScheduleWithRunLoop(fileOp, runLoop, kCFRunLoopDefaultMode);
    if( status )
    {
        NSLog(@"Failed to schedule operation with run loop: %@", status);
        return;
    }
  
    // Create a filesystem ref structure for the source and destination and
    // populate them with their respective paths from our NSTextFields.
    FSRef source;
    FSRef destination;
    
    FSPathMakeRef( (const UInt8 *)[[sourceURL path] fileSystemRepresentation], &source, NULL );
    
    Boolean isDir = true;
    FSPathMakeRef( (const UInt8 *)[[distURL path] fileSystemRepresentation], &destination, &isDir );    
    
    // Start the async copy.
    FSFileOperationClientContext clientContext = {0};
    clientContext.info = self;
    status = FSCopyObjectAsync (fileOp,
                                &source,
                                &destination, // Full path to destination dir
                                NULL, // Use the same filename as source
                                kFSFileOperationDefaultOptions,
                                statusCallback,
                                1.0,
                                &clientContext);
    
    CFRelease(fileOp);
    
    if( status )
    {
        NSLog(@"Failed to begin asynchronous object copy: %@", status);
    }

}
- (void)dealloc
{
    [sourceURL release];
    [distURL release];
    [super dealloc];
}

@end

このクラスにコピー元、コピー先のURLを渡して非同期コピーをする。 FSCopyObjectAsync を起動する以外は、コピー済みbytesを記録するだけ。

現在、動作を確認中。 FSCopyObjectAsync はコピー元としてディレクトリを渡したら、ディレクトリを1つのファイルのように扱ってもらえるようだ。

コピー元がディレクトリの場合、ディレクトリの中を再帰的に探索していってコピーするべきかどうか、とか、コピー済みbytesは正確に得られるかとかの検証は明日以降。

0 件のコメント:

コメントを投稿