微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

objective-c – 使用FSCopyObjectAsync显示文件复制进度

经过大量搜索后,在尝试执行文件复制并显示相对于已复制文件数量的进度指示器时,似乎存在常见问题.在花了相当长的时间试图解决这个问题后,我发现自己再次受到StackOverflow众神的支配:-) – 希望有一天我会成为那些可以帮助新手的人之一!

我试图获得一个进度条来显示复制过程的状态,一旦复制过程完成,调用Cocoa方法.挑战 – 我需要使用文件管理器碳调用,因为NSFileManager不能提供我所需的全部功能.

我开始试图利用Matt Long的网站Cocoa Is My Girlfriend上的代码.代码我有了一些很好的距离.我设法让文件复制进度正常工作.栏更新和(在Apple文档中进行一些额外搜索)我发现如何判断文件复制过程是否已完成…

if(stage == kFSOperationStageComplete)

但是,我有一个最后一个障碍,比我现在的飞跃大一点.我不知道如何将对象引用传递给回调,我不知道如何在回调完成后调用Cocoa方法.这是我的碳限制 – >可可 – >碳理解.其中一条评论博客上说

“Instead of accessing the progress indicator via a static pointer,you can just use the void *info field of the FSFileOperationClientContext struct,and passing either the AppDelegate or the progress indicator itself.”

这主意听起来很不错.不知道该怎么做.为了其他人似乎遇到这个问题并且来自非碳背景,主要基于Matt的例子中的代码,这里有一些简化的代码作为问题的一个例子……

在普通的可可方法中:

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 NO;
}

// Create a filesystem ref structure for the source and destination and 
// populate them with their respective paths from our NSTextFields.

FSRef source;
FSRef destination;

// Used FSPathMakeRefWithOptions instead of FSPathMakeRef which is in the 
// original example because I needed to use the kFSPathMakeRefDefaultOptions
// to deal with file paths to remote folders via a /Volume reference

FSPathMakeRefWithOptions((const UInt8 *)[aSource fileSystemRepresentation],kFSPathMakeRefDefaultOptions,&source,NULL);

Boolean isDir = true;

FSPathMakeRefWithOptions((const UInt8 *)[aDestDir fileSystemRepresentation],&destination,&isDir);

// Needed to change from the original to use CFStringRef so I Could convert
// from an Nsstring (aDestFile) to a CFStringRef (targetFilename)

CFStringRef targetFilename = (CFStringRef)aDestFile;

// Start the async copy.

status = FScopyObjectAsync (fileOp,// Full path to destination dir
             targetFilename,kFSFileOperationDefaultOptions,statusCallback,1.0,NULL);

CFRelease(fileOp);

if (status) {

    Nsstring * errMsg = [Nsstring stringWithFormat:@"%@ - %@",[self class],status];

        NSLog(@"Failed to begin asynchronous object copy: %@",status);
}

然后是回调(在同一个文件中)

static void statusCallback (FSFileOperationRef fileOp,const FSRef *currentItem,FSFileOperationStage stage,Osstatus error,CFDictionaryRef statusDictionary,void *info )
{

    NSLog(@"Callback got called.");

    // If the status dictionary is valid,we can grab the current values to 
    // display status changes,or in our case to update the progress indicator.

    if (statusDictionary)
    {

        CFNumberRef bytesCompleted;

        bytesCompleted = (CFNumberRef) CFDictionaryGetValue(statusDictionary,kFSOperationBytesCompleteKey);

        CGFloat floatBytesCompleted;
        CFNumberGetValue (bytesCompleted,kcfNumberMaxType,&floatBytesCompleted);

        NSLog(@"copied %d bytes so far.",(unsigned long long)floatBytesCompleted);

        // fileProgressIndicator is currently declared as a pointer to a 
        // static progress bar - but this needs to change so that it is a 
        // pointer passed in via the controller. Would like to have a 
        // pointer to an instance of a progress bar

        [fileProgressIndicator setDoubleValue:(double)floatBytesCompleted];
        [fileProgressIndicator displayIfNeeded];
     }

if (stage == kFSOperationStageComplete) {

    NSLog(@"Finished copying the file");

    // Would like to call a Cocoa Method here...
}

}

所以底线是我怎么能:

>将指针从调用方法传递到进度条的实例到回调
>完成后,回拨一个正常的Cocoa方法

和往常一样,非常感谢帮助(希望答案能解决我在许多线程中看到的许多问题和抱怨!)

解决方法

您可以使用FScopyObjectAsync()的最后一个参数来执行此操作,该参数是FSFileOperationClientContext类型的结构.该结构的一个字段是info,它是一个void *参数,您可以根据需要使用它.无论你分配给结构的那个字段,你传递给FScopyObjectAsync()将依次传递给你的回调函数作为那里的最后一个info函数参数. void *可以是任何东西,包括指向对象的指针,因此您可以使用它来传递要处理回调的对象实例.

设置代码如下所示:

FSFileOperationClientContext clientContext = {0}; //zero out the struct to begin with

clientContext.info = myProgressIndicator;
//All the other setup code
status = FScopyObjectAsync (fileOp,// Full path to destination dir
         targetFilename,&clientContext);

然后,在你的回调函数中:

static void statusCallback (FSFileOperationRef fileOp,void *info )
{
    nsprogressIndicator* fileProgressIndicator = (nsprogressIndicator*)info;
    [fileProgressIndicator setDoubleValue:(double)floatBytesCompleted];
    [fileProgressIndicator displayIfNeeded];
}

原文地址:https://www.jb51.cc/c/118264.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐