Как я могу получить значок для устройства хранения в Mac OS X? - PullRequest
3 голосов
/ 24 февраля 2009

Я нашел мои устройства, используя IOServiceGetMatchingServices, и получил словарь свойств, подобный этому:

kernResult = IORegistryEntryCreateCFProperties(nextMedia,
                    (CFMutableDictionaryRef *)&props,
                                              kCFAllocatorDefault, 0);

Из этого словаря я могу извлечь информацию для значков:

NSString *bId = [props valueForKeyPath:@"IOMediaIcon.CFBundleIdentifier"];
NSString *rFile = [props valueForKeyPath:@"IOMediaIcon.IOBundleResourceFile"];

Эти двое дают мне (например):

com.apple.iokit.IOStorageFamily   (Bundle identifier)
Internal.icns                     (Resource File)

Я попытался извлечь значок, используя этот метод:

NSBundle *bundleWithIcon = [NSBundle bundleWithIdentifier:bId];
NSString *iconPath = [bundleWithIcon pathForResource:rFile ofType:nil];

Но bundleWithIcon - это nil.

Это даже правильный способ получить иконку?

Я думаю, мне нужно как-то загрузить пакет, чтобы иметь возможность загрузить его с bundleWithIdentifier, как я могу это сделать?

PS: Есть еще один вопрос , который (я думаю) пытается задать то же самое, но запрашивает только связки, не если это правильный путь.

Ответы [ 5 ]

7 голосов
/ 25 февраля 2009

Вы можете использовать NSWorkspace.
Исходное изображение 32x32, но оно имеет представления для других размеров и будет соответственно масштабироваться

NSWorkspace * ws = [NSWorkspace sharedWorkspace];
NSImage * icon = [ws iconForFile:@"/Volumes/Whatever"];
NSLog(@"%@", [icon representations]); // see what sizes the icon has
icon.size = NSMakeSize(512, 512);
2 голосов
/ 24 февраля 2009

Совсем недавно Эндрю Майрик ответил на аналогичный вопрос в списке рассылки darwin-dev:

KextManagerCreateURLForBundleIdentifier() в <IOKit/kext/KextManager.h> может быть использования, хотя я считаю, что это работает только для кексов, которые либо 1) загружены, или 2) в / S / L / E /. Вот снег Leopard headerdoc:

/*!
 * @function KextManagerCreateURLForBundleIdentifier
 * @abstract Create a URL locating a kext with a given bundle identifier.
 *
 * @param    allocator
 *           The allocator to use to allocate memory for the new object.
 *           Pass <code>NULL</code> or <code>kCFAllocatorDefault</code>
 *           to use the current default allocator.
 * @param    kextIdentifier
 *           The bundle identifier to look up.
 *
 * @result
 * A CFURLRef locating a kext with the requested bundle identifier.
 * Returns <code>NULL</code> if the kext cannot be found, or on error.
 *
 * @discussion
 * Kexts are looked up first by whether they are loaded, second by version.
 * Specifically, if <code>kextIdentifier</code> identifies a kext
 * that is currently loaded,
 * the returned URL will locate that kext if it's still present on disk.
 * If the requested kext is not loaded,
 * or if its bundle is not at the location it was originally loaded from,
 * the returned URL will locate the latest version of the desired kext,
 * if one can be found within the system extensions folder.
 * If no version of the kext can be found, <code>NULL</code> is returned.
 */
CFURLRef KextManagerCreateURLForBundleIdentifier(
    CFAllocatorRef allocator,
    CFStringRef    kextIdentifier);

Обратите внимание, что до снежного барса это может работать только для kexts в / S / L / E; API существовал, но не было headerdoc, описывающий его поведение.

Для меня это очень хорошо работало на Mac OS X 10.5.

1 голос
/ 12 мая 2009

это может вам помочь. (а может и нет) ...

Играя с командой 'ioreg', я наткнулся на что-то, что напомнило мне ваш вопрос, и поэтому я опубликую его:

попробуйте ввести следующую команду:

ioreg -c IOMedia -x

, что приведет к большому беспорядку вывода, который выглядит примерно так:

  |     +-o IOBlockStorageDriver  <class IOBlockStorageDriver, registered, matched, active, busy 0, retain 7>
  |       +-o Apple read/write Media  <class IOMedia, registered, matched, active, busy 0, retain 9>
  |         | {
  |         |   "Removable" = Yes
  |         |   "BSD Unit" = 0x4
  |         |   "IOBusyInterest" = "IOCommand is not serializable"
  |         |   "BSD Minor" = 0xc
  |         |   "Ejectable" = Yes
  |   |         |   "BSD Name" = "disk4"
  |         |   "Leaf" = No
  |         |   "IOMediaIcon" = {"CFBundleIdentifier"="com.apple.iokit.IOStorageFamily","IOBundleResourceFile"="Removable.icns"}
  |         |   "Preferred Block Size" = 0x200
  |         |   "Whole" = Yes
  |         |   "Open" = Yes
  |         |   "Size" = 0x100000
  |         |   "Writable" = Yes
  |         |   "Content" = "Apple_partition_scheme"
  |         |   "IOGeneralInterest" = "IOCommand is not serializable"
  |         |   "Content Hint" = ""
  |         | }         |   "BSD Major" = 0xe

все это заставляет меня поверить (и, следовательно, здесь вслепую рекомендует вам провести расследование), что если вы пройдете по дереву реестра io, совпадающему с IOMedia, вы можете получить словари свойств, которые будут содержать запись с ключом "IOMediaIcon", которая сама по себе появляется быть коллекцией, информирующей вас об идентификаторе пакета и имени файла ресурса.

Нельзя сказать, что это легко ... но посмотрите FireWire SDK , чтобы найти весь пример кода, который вам может понадобиться ... в любом случае это, вероятно, «лучше», чем жестко заданные предварительно заполненные пути (которые могут исчезнуть в будущих выпусках ОС).

| K <</p>

0 голосов
/ 14 октября 2009

Том без пользовательского значка будет отображаться с одним из общих значков ОС, к которому вы жестко запрограммировали пути. Том с пользовательским значком будет хранить этот значок в своей файловой системе, и, если он не смонтирован, поиск станет полностью вашей работой.

0 голосов
/ 24 февраля 2009

Эти двое дают мне (например):

com.apple.iokit.IOStorageFamily (идентификатор пакета) Internal.icns (файл ресурсов)

Я пытался извлечь значок, используя этот метод:

NSBundle * bundleWithIcon = [NSBundle bundleWithIdentifier: bId]; NSString * iconPath = [bundleWithIcon pathForResource: rFile ofType: nil];

Но bundleWithIcon - это nil.

bundleWithIdentifier: требует, чтобы вы уже создали экземпляр NSBundle для пакета с этим идентификатором; он ищет только ранее созданный экземпляр. Поэтому вам нужно найти пакет в файловой системе и создать его экземпляр по пути. К счастью, у вас, похоже, уже есть ссылка на вопрос об этом.

...