我试图获得一个进度条来显示复制过程的状态,一旦复制过程完成,调用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方法
和往常一样,非常感谢帮助(希望答案能解决我在许多线程中看到的许多问题和抱怨!)
解决方法
设置代码如下所示:
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]; }