Как проверить, отображаются ли каталоги с заданным расширением в Finder как пакет?

Для данного расширения, как вы проверяете, будут ли каталоги с этим расширением отображаться в Finder как пакет?

Я полагал, что приведенный ниже метод является эффективной реализацией для этого, но создание временного каталога похоже на взлом. Я предполагаю, что смогу правильно реализовать это через 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»).


person Rinzwind    schedule 05.06.2013    source источник


Ответы (1)


Вы можете запросить информацию об Uniform Type Identifier. для вашего расширения.
Сначала вам нужно выяснить правильный 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 описывается, как определить UTI для приложения на основе документов (которые часто используют NSFileWrappers и пакеты документов): https://developer.apple.com/library/mac/documentation/DataManagement/Conceptual/DocBasedAppProgrammingGuideForOSX/ApplicationCreationProcess/ApplicationCreationProcess.html#//apple_ref/doc/uid/TP40011179-CH6-997699

Update2:
В дополнение к UTI, соответствующему kUTTypePackage или kUTTypeBundle, существует атрибут файла Package Bit, который также может помечать папку как пакет:

Из документации Apple:

Как система идентифицирует пакеты и пакеты. Finder считает каталог пакетом, если выполняется одно из следующих условий:

  • Каталог имеет известное расширение имени файла: .app, .bundle, .framework, .plugin, .kext и т. д.
  • Каталог имеет расширение, которое, как утверждают некоторые другие приложения, представляет тип пакета; см. «Пакеты документов».
  • В каталоге установлен пакетный бит.

Update3:
Описанный выше подход на основе UTI не охватывает все случаи, которые Finder принимает во внимание при проверке того, является ли папка пакетом или бандлом.
Его можно использовать для проверьте, соответствует ли конкретный UTI kUTTypeBundle или kUTTypePackage.

person Thomas Zoechling    schedule 05.06.2013
comment
Спасибо за ответ. Я проверил вашу реализацию и обнаружил, что она дает другой результат для расширения esproj (у меня установлен Espresso 2.0.5, macrabbit. com/espresso): реализация «временного каталога» возвращает YES (соответствует поведению Finder), а реализация UTI возвращает NO. У вас есть идеи, почему это может быть? - person Rinzwind; 05.06.2013
comment
Вероятно, это зависит от того, что приложение, объявляющее UTI (Espresso в вашем случае), определяет в своем plist. Я обновил свой ответ, чтобы также проверить kUTTypeBundle. - person Thomas Zoechling; 05.06.2013
comment
Я попытался отредактировать код, чтобы также проверить kUTTypeBundle, но он по-прежнему возвращает НЕТ для esproj. Я добавил NSLog для UTI и обнаружил, что он начинается с dyn.; что, если я правильно понимаю документацию, означает, что UTTypeCreatePreferredIdentifierForTag не нашел подходящего UTI и просто создал «поддельный» динамический. Можете ли вы подтвердить это поведение после установки Espresso 2.0.5? - person Rinzwind; 05.06.2013
comment
Это работает для других пакетов? Возможно, он просто не возвращает предпочтительный тип. Вы можете попробовать использовать UTTypeCreateAllIdentifiersForTag и перебрать его, проверяя, является ли один идентификатор пакетом. - person Thomas Zoechling; 05.06.2013
comment
Расширения, для которых «временный каталог» и реализации UTI дают одинаковый результат: rtf, rtfd, app, txt. Расширения с разными результатами (первое внедрение ДА, второе НЕТ): esproj, dtps, kext. Для этих трех UTTypeCreateAllIdentifiersForTag возвращает массив с одним элементом, строку, начинающуюся с dyn. Можете ли вы подтвердить такое же поведение на вашем компьютере для kext? Не требует установки какого-либо приложения (kext = расширение ядра). - person Rinzwind; 05.06.2013
comment
Я получаю те же результаты для kexts. Возможно, вам придется использовать обходной путь вашего файла tmp. Подход, основанный на UTI, который я придумал, не охватывает все варианты использования. Я узнал, что есть также бит пакета, который может пометить папку как пакет, но он не установлен для кекстов. Подробности: stackoverflow.com/questions/2009687/ - person Thomas Zoechling; 05.06.2013
comment
Спасибо за подтверждение примера kext и за вашу помощь! Для дальнейшего использования я отредактировал тест в своем вопросе, чтобы отразить дополнительные примеры, которые мы обсуждали, на случай, если кто-то предложит другой подход к реализации (который должен, по крайней мере, пройти этот тест). На данный момент я буду придерживаться «взломной» реализации. - person Rinzwind; 05.06.2013