Размонтировать диск в OSX с помощью DiskArbitration
Я пытаюсь размонтировать диск в 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");
}
}
Обновление. Благодаря Кену Томасесу код теперь работает
- (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);
}
1 ответ
DADiskUnmount()
работает асинхронно. Диск не обязательно был размонтирован к моменту возврата функции в ваш код. Если это удастся, это может произойти в более позднее время. Ваш обратный вызов будет вызван в это время.
Механизм, с помощью которого программа ожидает этого события и вызывает ваш ответный вызов, является либо циклом выполнения, либо очередью отправки. Объект сеанса отвечает за управление этим ожиданием и вызовом. Вам необходимо запланировать объект сеанса в цикле выполнения или очереди отправки. Вы используете либо DASessionScheduleWithRunLoop()
или же DASessionSetDispatchQueue()
, как описано в Руководстве по программированию дискового арбитража: Использование уведомлений и ответных вызовов для арбитража диска - Планирование сеанса с помощью цикла выполнения или очереди отправки.
Это означает, что вы не хотите создавать новый объект сеанса для каждой попытки размонтировать диск. Кроме того, вы хотите сохранить ссылку на объект сеанса, чтобы вы могли отменять планирование и освобождать его, когда он вам больше не нужен (что может случиться через некоторое время после того, как вам больше не понадобится обратный вызов от него).