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(),如Disk Arbitration Programming Guide: Using Disk Arbitration Notification and Approval Callbacks – Scheduling the Session with the Run Loop or Dispatch Queue中所述。

这意味着您不想为每次卸载磁盘的尝试创建一个新的会话对象。此外,您希望保留对会话对象的引用,以便您可以在不再需要它时取消调度并释放它(这将在您不再需要从中获取回调之后的某个时间)。

于 2016-01-01T05:09:16.053 回答