以下代码用于获取磁盘列表
(void)da_tools
{
DASessionRef session;
session = DASessionCreate(kCFAllocatorDefault);
DARegisterDiskAppearedCallback(session, NULL, disk_appeared_callback, (void *)NULL);
DASessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFRunLoopRun();
CFRelease(session);
}
“确定”按钮的IBAction为:[self da_tools]
;
回调函数 disk_appeared_callback 完美运行并提供正确的信息。
当点击确定按钮时,问题发生在 CFRunLoopRun():
然而,任何键按下键盘(或鼠标点击任何地方(有时只是鼠标移动)) 强制 CFRunLoopRun()退出,并立即执行回调函数 disk_appeared_callback 。
删除 CFRunLoopRun()时da_tools
在第一个OK按钮命中时不返回任何磁盘信息
但随后的OK按钮命中将返回正确的磁盘信息。
我试图将da_tools
包含在另一个帖子中:
[NSThread detachNewThreadSelector:@selector(da_tools) toTarget:self withObject:nil]
但这没有帮助。
我也试图发布一个keydown事件,但这也失败了。
如何正确使用 CFRunLoopRun ?
答案 0 :(得分:1)
请不要单独使用CFRunLoopRun();
方法,请不要发布会话CFRelease(session);
,因为稍后您不会收到任何回调。
如何与DiskArbitration建立会话并通过回调收听?
创建DA会话并安排会话运行循环:
// Disk Arbitration Session
DASessionRef session = DASessionCreate(kCFAllocatorDefault);
if (!session) {
[NSException raise:NSGenericException format:@"Unable to create Disk Arbitration session."];
return;
}
NSLog(@"Disk Arbitration Session created");
// schedule DA session run loop
DASessionScheduleWithRunLoop(session, CFRunLoopGetMain(), kCFRunLoopCommonModes);
如果您想收听包括内部事件在内的所有磁盘事件。然后在注册回调时传递NULL
。
否则为您的回调创建matching condition
。例如:以下条件为外部硬盘,内存磁盘通过USB连接。
// Matching Conditions
CFMutableDictionaryRef match = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
// Device matching criteria
// 1. Of-course it shouldn't be internal device since
CFDictionaryAddValue(match, kDADiskDescriptionDeviceInternalKey, kCFBooleanFalse);
// Volume matching criteria
// It should statisfy following
CFDictionaryAddValue(match, kDADiskDescriptionVolumeMountableKey, kCFBooleanTrue);
CFDictionaryAddValue(match, kDADiskDescriptionVolumeNetworkKey, kCFBooleanFalse);
查看DADisk.h
,我们会根据您的需要添加更多条件。
使用DiskArbitration注册回调,有关回调的更多信息here -
NSString * const AppName = @"DAApp";
// Registring callbacks
DARegisterDiskAppearedCallback(session, match, DiskAppearedCallback, (__bridge void *)AppName);
DARegisterDiskDisappearedCallback(session, match, DiskDisappearedCallback, (__bridge void *)AppName);
DARegisterDiskDescriptionChangedCallback(session, match, NULL, DiskDescriptionChangedCallback, (__bridge void *)AppName);
// And now release match
CFRelease(match);
......申请事情四处传播...... **
最后取消注册并发布所有内容。典型的地方是申请终止或dealloc。
// DA Session
if (session) {
DAUnregisterCallback(session, DiskAppearedCallback, (__bridge void *)AppName);
DAUnregisterCallback(session, DiskDisappearedCallback, (__bridge void *)AppName);
DASessionUnscheduleFromRunLoop(session, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFRelease(session);
NSLog(@"Disk Arbitration Session destoryed");
}
我希望它有所帮助!
顺便说一下,像这样的DA审批会议
// Disk Arbitration Approval Session
DASessionRef approvalSession = DAApprovalSessionCreate(kCFAllocatorDefault);
if (!approvalSession) {
NSLog(@"Unable to create Disk Arbitration approval session.");
return;
}
NSLog(@"Disk Arbitration Approval Session created");
DAApprovalSessionScheduleWithRunLoop(approvalSession, CFRunLoopGetMain(), kCFRunLoopCommonModes);
// Same match condition for Approval session too
DARegisterDiskMountApprovalCallback(approvalSession, match, DiskMountApprovalCallback, (__bridge void *)AppName);
// may need CFRelease(match); based code sequence!
最后取消注册并发布。
// DA Approval Session
if (approvalSession) {
DAUnregisterApprovalCallback(approvalSession, DiskMountApprovalCallback, (__bridge void *)AppName);
DAApprovalSessionUnscheduleFromRunLoop(approvalSession, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFRelease(approvalSession);
NSLog(@"Disk Arbitration Approval Session destoryed");
}
有关上述代码段here的更多信息。