1

对于给定的扩展,如何检查具有该扩展的目录是否会被 Finder 显示为一个包?

我认为下面的方法是一个有效的实现,但是创建一个临时目录感觉就像一个 hack。我猜我应该能够通过Launch Services API正确实现这一点,但我不太清楚该怎么做(虽然我可能忽略了显而易见的事情)。

// Extension method on NSWorkspace
@implementation NSWorkspace (MyExtraMethods)
- (BOOL) isPackageExtension: (NSString*) extension
{
    NSString * pathToTemp = [NSTemporaryDirectory() stringByAppendingPathComponent:[@"Untitled" stringByAppendingPathExtension: extension]];
    [[NSFileManager defaultManager] createDirectoryAtPath:pathToTemp withIntermediateDirectories:NO attributes:nil error:NULL];
    BOOL result = [[NSWorkspace sharedWorkspace] isFilePackageAtPath: pathToTemp];
    [[NSFileManager defaultManager] removeItemAtPath:pathToTemp error:NULL];
    return result;
}
@end

// Basic test for the above
- (void) testIsPackageExtension
{
    STAssertFalse([[NSWorkspace sharedWorkspace] isPackageExtension: @"txt"], @"");
    STAssertFalse([[NSWorkspace sharedWorkspace] isPackageExtension: @"rtf"], @"");

    STAssertTrue([[NSWorkspace sharedWorkspace] isPackageExtension: @"rtfd"], @"");
    STAssertTrue([[NSWorkspace sharedWorkspace] isPackageExtension: @"app"], @"");
    STAssertTrue([[NSWorkspace sharedWorkspace] isPackageExtension: @"kext"], @"");
    STAssertTrue([[NSWorkspace sharedWorkspace] isPackageExtension: @"clr"], @"");

    /* The following tests depend on having applications installed
       that are not included in Mac OS X:
        .esproj   Espresso, tested with version 2.0.5 ( http://macrabbit.com/espresso/ )
        .dtps     Instruments, included in Xcode, tested with version 4.5 (4523) */
    STAssertTrue([[NSWorkspace sharedWorkspace] isPackageExtension: @"esproj"], @"");
    STAssertTrue([[NSWorkspace sharedWorkspace] isPackageExtension: @"dtps"], @"");
}

编辑:上面的测试已经过编辑,包括额外的示例扩展(原始帖子仅使用“rtf”和“rtfd”)。

4

1 回答 1

1

您可以查询扩展的统一类型标识符信息
您首先必须找出正确的 UTI,然后测试它是否符合com.apple.package(声明为 kUTTypePackage):

- (BOOL)isPackageTypeForExtension:(NSString*)extension
{
    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)(extension), NULL);
    return UTTypeConformsTo(UTI, kUTTypePackage);
}

更新:
此外,您可以检查 kUTTypeBundle:

 UTTypeConformsTo(UTI, kUTTypeBundle)

并将OR (|)结果转换为上述方法的返回值。

以下 Apple 文档描述了如何为基于文档的应用程序(通常使用 NSFileWrappers 和文档包)定义 UTI: https ://developer.apple.com/library/mac/documentation/DataManagement/Conceptual/DocBasedAppProgrammingGuideForOSX/ApplicationCreationProcess/ApplicationCreationProcess .html#//apple_ref/doc/uid/TP40011179-CH6-997699

Update2:
除了符合 kUTTypePackage 或 kUTTypeBundle 的 UTI 外,还有一个 Package Bit 文件属性,它也可以将文件夹标记为包:

苹果的文档

系统如何识别 Bundles 和 Packages 如果满足以下任一条件,Finder 会将目录视为一个包:

  • 该目录具有已知的文件扩展名:.app、.bundle、.framework、.plugin、.kext 等。
  • 该目录有一个扩展名,其他一些应用程序声称它代表一个包类型;请参阅“文档包”。
  • 该目录设置了其包位。

更新 3 :
上述基于 UTI 的方法并未涵盖 Finder 在测试文件夹是包还是捆绑包时考虑的所有情况。
它可用于测试特定 UTI 是否符合 kUTTypeBundle 或 kUTTypePackage。

于 2013-06-05T08:33:51.160 回答