Frage

Es erscheint nach langer Suche, dass es ein weit verbreitetes Problem zu sein scheint, wenn man versucht, eine Datei zu kopieren zu tun und zeigt eine Fortschrittsanzeige im Verhältnis zur Menge der Datei, die kopiert wurde. geraume Zeit versucht, dieses Problem, nachdem er zu lösen, ich mich auf die Gnade der Götter finden Stackoverflow wieder :-) - Hoffentlich eines Tages werde ich unter denen sein werde, dass auch die Rookies helfen kann

!

Ich versuche, einen Fortschrittsbalken zu erhalten, den Status eines Kopiervorganges zu zeigen, und sobald der Kopiervorgang beendet ist, rufen Sie eine Kakao-Methode. Die Herausforderung - ich brauche, um die Verwendung von File Manager Carbon-Anrufe zu machen, weil NSFileManager geben Sie mir nicht die volle Fähigkeit, ich brauche

.

Ich begann, indem Sie versuchen, den Code auf Matt Long Seite Cocoa Is My Girlfriend . Der Code hat mir einige gute Entfernung. Ich schaffte es die Datei Kopie Fortschritte zum Laufen zu bringen. Die Bar-Updates und (mit einigen zusätzlichen Suche innerhalb Apple-docs) fand ich heraus, wie zu sagen, ob der Kopiervorgang ...

beendet hat

if (stage == kFSOperationStageComplete)

Allerdings habe ich noch eine letzte Hürde, die gerade jetzt ein wenig größer als mein Sprung ist. Ich weiß nicht, wie ein Objektverweis in den Rückruf passieren, und ich weiß nicht, wie man eine Cocoa-Methode aus dem Rückruf anrufen einmal beendet. Dies ist eine Grenze meiner Kohlenstoff -> Kakao -> Kohlenstoff Verständnis. Einer der Kommentare auf dem Blog sagte

„Statt die Fortschrittsanzeige über einen statischen Zeiger zugreifen, können Sie die void * Info-Feld der FSFileOperationClientContext Struktur benutzen Sie einfach und Leiten entweder die AppDelegate oder die Statusanzeige selbst.“

klingt wie eine gute Idee. Nicht sicher, wie dies zu tun. Aus Gründen der alle anderen, das erscheint in dieser Frage zu stoßen und aus einem nicht-Carbon-Hintergrund kommen, basiert vor allem auf dem Code von Matts Beispiel, hier einige vereinfachte Code als ein Beispiel für das Problem ...

In einer normalen Kakao-Methode:

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

Dann wird der Rückruf (in der gleichen Datei)

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...
}

} 

So lautet das Fazit ist, wie kann ich:

  1. Führen Sie einen Zeiger auf eine Instanz eines Fortschrittsbalkens aus dem Aufruf der Methode an die Callback
  2. Nach der Fertigstellung Rückruf aus einer normalen Cocoa Methode

Und wie immer, ist Hilfe sehr geschätzt (und hoffentlich wird die Antwort viele der Probleme zu lösen und Beschwerden, die ich in vielen Threads gesehen habe !!)

War es hilfreich?

Lösung

Sie können dies tun, indem Sie den letzten Parameter FSCopyObjectAsync() verwenden, die eine Struktur des Typs FSFileOperationClientContext ist. Eines der Felder dieser Struktur ist info, das ist ein void * Parameter, dass Sie im Grunde, wie Sie sehen, passen können. Was auch immer Sie zuweisen, um das Feld der Struktur Du in FSCopyObjectAsync() passieren wird wiederum auf Ihre Callback-Funktion als letzten info Funktionsparameter dort übergeben werden. Ein void * kann alles sein, ein Zeiger auf ein Objekt einschließlich, so Sie verwenden, können Sie die Instanz des Objekts passieren, dass Sie den Rückruf behandeln möchten.

Der Code-Setup würde wie folgt aussehen:

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

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

Dann in Ihrer Callback-Funktion:

static void statusCallback (FSFileOperationRef fileOp,
       const FSRef *currentItem,
       FSFileOperationStage stage,
       OSStatus error,
       CFDictionaryRef statusDictionary,
       void *info )
{
    NSProgressIndicator* fileProgressIndicator = (NSProgressIndicator*)info;
    [fileProgressIndicator setDoubleValue:(double)floatBytesCompleted];
    [fileProgressIndicator displayIfNeeded];
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top