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