【问题标题】:How to check whether directories with a given extension are shown by the Finder as a package?如何检查 Finder 是否将具有给定扩展名的目录显示为一个包?
【发布时间】:2013-06-05 19:49:09
【问题描述】:

对于给定的扩展,如何检查具有该扩展的目录是否会被 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”)。

【问题讨论】:

    标签: objective-c cocoa finder nsworkspace


    【解决方案1】:

    您可以查询Uniform Type Identifier information 以获得您的分机。
    您首先必须找出正确的 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

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

    来自Apple's documentation

    系统如何识别捆绑包和包 Finder 认为 如果满足以下任一条件,则目录为包:

    • 该目录具有已知的文件扩展名:.app、.bundle、 .framework、.plugin、.kext 等等。
    • 目录有扩展名 其他一些应用程序声明代表一种包装类型;看 “文件包。”
    • 目录已设置其包位。

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

    【讨论】:

    • 感谢您的回答。我测试了你的实现,发现它对扩展“esproj”给出了不同的结果(我安装了 Espresso 2.0.5,macrabbit.com/espresso):“临时目录”实现返回 YES(对应于 Finder 的行为),而 UTI执行返回 NO。你知道为什么会这样吗?
    • 这可能取决于 UTI 声明应用程序(在您的情况下为 Espresso)在其 plist 中定义的内容。我更新了我的答案以检查 kUTTypeBundle。
    • 我尝试编辑代码以检查 kUTTypeBundle,但它仍然为“esproj”返回 NO。我为UTI添加了一个NSLog,发现它以“dyn”开头;如果我正确理解文档,这意味着 UTTypeCreatePreferredIdentifierForTag 没有找到匹配的 UTI,只是创建了一个“假”动态的。你能在安装 Espresso 2.0.5 后确认这个行为吗?
    • 它适用于其他软件包吗?也许它只是不返回“首选”类型。您可以尝试使用 UTTypeCreateAllIdentifiersForTag 并对其进行迭代,测试一个标识符是否是一个包。
    • “临时目录”和 UTI 实现给出相同结果的扩展:rtf、rtfd、app、txt。具有不同结果的扩展(第一次实现是,第二次否):esproj、dtps、kext。对于这三个 UTTypeCreateAllIdentifiersForTag 返回一个包含单个元素的数组,一个以“dyn.”开头的字符串。你能在你的机器上确认“kext”的相同行为吗?它不需要安装任何应用程序(“kext”=内核扩展)。
    猜你喜欢
    • 2016-01-28
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 2012-04-02
    • 2017-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多