4

OSX でディスクをアンマウントしようとしています。コードは正常に動作しますが、エラーが発生した場合にのみ、ディスクが正常にアンマウントされたときにコールバックが呼び出されません。DiskArbitrationProgGuide を読み、手順に従いましたが、まだ進展がありません。誰か助けてくれませんか?

@interface DriverUtilitiesController()

void unmount_done(DADiskRef disk,
                  DADissenterRef dissenter,
                  void *context);

@end

+ (void)umnountDrivePath:(NSString *)voulumePath
{
    DASessionRef session = DASessionCreate(kCFAllocatorDefault);

    CFURLRef path = CFURLCreateWithString(NULL, (__bridge CFStringRef)voulumePath, NULL);

    DADiskRef disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, session, path);

    DADiskUnmount(disk, kDADiskUnmountOptionDefault, unmount_done, NULL);

    CFRelease(disk);
}

#pragma mark - Unmount Callback

void unmount_done(DADiskRef disk,
                  DADissenterRef dissenter,
                  void *context)
{

    NSLog(@"Inside unmount_done");

    if (dissenter)
    {
        // Unmount failed. //
        NSLog(@"Unmount failed.");

    } else {
        NSLog(@"Unmounted Volume");
    }
}

更新中。Ken Thomases のおかげで、コードが動作するようになりました

- (id)init
{
    self = [super init];

    self.session = DASessionCreate(kCFAllocatorDefault);

    DASessionScheduleWithRunLoop(_session, [[NSRunLoop mainRunLoop] getCFRunLoop], kCFRunLoopDefaultMode);

    return self;
}


- (void)umnountDrivePath:(NSString *)voulumePath
{

    CFURLRef path = CFURLCreateWithString(NULL, (__bridge CFStringRef)voulumePath, NULL);

    DADiskRef disk = DADiskCreateFromVolumePath(kCFAllocatorDefault, self.session, path);

    DADiskUnmount(disk, kDADiskUnmountOptionDefault, unmount_done, (__bridge void *)(self));

    CFRelease(disk);
}

void unmount_done(DADiskRef disk,
                  DADissenterRef dissenter,
                  void *context)
{
    if (dissenter)
    {
        // Unmount failed. //
        NSLog(@"Unmount failed.");

    } else {
        NSLog(@"Unmounted Volume");

    }

    DriverUtilitiesController *driverUtilitiesController = (__bridge DriverUtilitiesController *)context;


    [driverUtilitiesController clearUnmountCallback];
}

- (void)clearUnmountCallback
{
    DASessionUnscheduleFromRunLoop(_session, [[NSRunLoop mainRunLoop] getCFRunLoop], kCFRunLoopDefaultMode);

    CFRelease(self.session);
}
4

1 に答える 1

3

DADiskUnmount()非同期で動作します。関数がコードに戻るまでに、必ずしもディスクがアンマウントされているとは限りません。成功した場合、後で発生する可能性があります。その時点でコールバックが呼び出されます。

プログラムがそのイベントを待機し、応答としてコールバックを呼び出すメカニズムは、実行ループまたはディスパッチ キューのいずれかです。セッション オブジェクトは、この待機と呼び出しの管理を担当します。実行ループまたはディスパッチ キューでセッション オブジェクトをスケジュールする必要があります。ディスク アービトレーション プログラミング ガイド: ディスク アービトレーション通知および承認コールバックの使用 – 実行ループまたはディスパッチ キューを使用したセッションのスケジューリング で説明されているように、DASessionScheduleWithRunLoop()またはのいずれかを使用します。DASessionSetDispatchQueue()

つまり、ディスクをアンマウントしようとするたびに新しいセッション オブジェクトを作成したくないということです。また、セッション オブジェクトへの参照を保持して、不要になったときにスケジュールを解除して解放できるようにする必要があります (コールバックを取得する必要がなくなった後)。

于 2016-01-01T05:09:16.053 に答える