После долгих поисков кажется, что при попытке сделать копию файла возникает общая проблема, и отображается индикатор прогресса относительно объема скопированного файла. Потратив немало времени, пытаясь решить эту проблему, я снова попадаю в зависимость от богов StackOverflow :-) - Надеюсь, однажды я окажусь среди тех, кто тоже может помочь новичкам!
Я пытаюсь получить индикатор выполнения, показывающий состояние процесса копирования, и после завершения процесса копирования вызовите метод Какао. Задача - мне нужно использовать вызовы File Manager Carbon, потому что NSFileManager не дает мне всех необходимых возможностей.
Я начал с попытки использовать код на сайте Мэтта Лонга Cocoa Is My Girlfriend . Код дал мне хорошую дистанцию. Мне удалось заставить работать копию файла. Панель обновляется, и (с дополнительным поиском в документах Apple) я узнал, как определить, завершился ли процесс копирования файла ...
if (stage == kFSOperationStageComplete)
Однако у меня есть последнее препятствие, которое сейчас немного больше, чем мой прыжок. Я не знаю, как передать ссылку на объект в обратный вызов, и я не знаю, как вызвать метод Какао из обратного вызова после завершения. Это предел моего понимания углерода -> какао -> углерода. Один из комментариев в блоге сказал
"Вместо того, чтобы обращаться к индикатору прогресса через статический указатель, вы можете просто использовать информационное поле void * структуры FSFileOperationClientContext и передать либо AppDelegate, либо сам индикатор прогресса."
Звучит как отличная идея. Не уверен, как это сделать. Ради всех остальных, кто, кажется, сталкивается с этой проблемой и прибывает из неуглеродного фона, основанного главным образом на коде из примера Мэтта, вот некоторый упрощенный код как пример проблемы ...
В обычном методе какао:
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],
kFSPathMakeRefDefaultOptions,
&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,
&source,
&destination, // 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...
}
}
Итак, суть в том, как я могу:
- Передать указатель на экземпляр индикатора выполнения из вызывающего метода в обратный вызов
- После завершения отзовитесь к обычному методу Какао
И, как всегда, помощь очень ценится (и, надеюсь, ответ решит многие проблемы и жалобы, которые я видел во многих темах !!)