Como posso obter o ícone de um dispositivo de armazenamento no Mac OS X?

StackOverflow https://stackoverflow.com/questions/580002

  •  06-09-2019
  •  | 
  •  

Pergunta

Eu encontrei meus dispositivos usando IOServiceGetMatchingServices e tem a propriedade de dicionário como este:

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

A partir desse dicionário posso extrair as informações para os ícones:

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

Esses dois me este dar (como um exemplo):

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

Eu tentei extrair o ícone usando este método:

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

Mas bundleWithIcon é nil.

É este mesmo o método correto para obter o ícone?

Eu acho que tem que carregar alguma forma o pacote para ser capaz de carregá-lo com bundleWithIdentifier, como posso fazer isso?

PS: Há outra questão que (eu acho) tenta fazer a mesma coisa, mas apenas pede pacotes, não se esta é a maneira correta.

Foi útil?

Solução 2

Apenas recentemente Andrew Myrick respondeu a uma pergunta semelhante na lista darwin-dev mailing:

KextManagerCreateURLForBundleIdentifier() em <IOKit/kext/KextManager.h> pode ser de uso, embora eu acredite que ele só funciona para kexts que são ou 1) carregado, ou 2) em / S / G / E /. Aqui está a neve 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);

Note que antes de Snow Leopard, ele pode funcionar apenas para kexts em / S / G / E; a API existia, mas não há nenhuma foi headerdoc descrevendo seu comportamento.

Para mim, isso funcionou muito bem no Mac OS X 10.5.

Outras dicas

Você pode usar NSWorkspace.
A imagem inicial é de 32x32, mas tem representações para os outros tamanhos e será ampliado em conformidade

NSWorkspace * ws = [NSWorkspace sharedWorkspace];
NSImage * icon = [ws iconForFile:@"/Volumes/Whatever"];
NSLog(@"%@", [icon representations]); // see what sizes the icon has
icon.size = NSMakeSize(512, 512);

isso pode ajudá-lo. (Ou talvez não) ...

em brincar com o comando 'ioreg' me deparei com algo que me fez lembrar da sua pergunta, e então eu vou postá-lo:

tente emitir o seguinte comando:

ioreg -c IOMedia -x

que irá produzir uma grande confusão de saída que é algo como isto:

  |     +-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

Esta tudo leva-me a acreditar (e, portanto, aqui cegamente recomendamos que você investigue) que se você atravessar a correspondência árvore de registro io contra 'IOMedia' você pode obter dicionários de propriedade que vai conter uma entrada com chave "IOMediaIcon", que se parece ser uma coleção informá-lo de um identificador de conjunto e um nome de arquivo de recurso.

não quer dizer que isso é fácil ... mas olhar para o FireWire SDK para todo o código exemplo, você pode precisar ... em qualquer caso, provavelmente é "melhor" do que caminhos pré-cheias embutir (que pode desaparecer em versões futuras do sistema operacional).

| K <

Esses dois me este dar (como um exemplo):

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

Eu tentei extrair o ícone usando este método:

NSBundle * bundleWithIcon = [NSBundle bundleWithIdentifier: Proposta]; NSString * IconPath = [bundleWithIcon pathForResource: rarquivo OfType: nil];

Mas bundleWithIcon é nil.

bundleWithIdentifier: requer que você já tenha criado uma instância NSBundle para um pacote com esse identificador; ele só olha para uma instância criada anteriormente. Portanto, você precisa encontrar o pacote no sistema de arquivos e instanciá-lo pelo caminho. Felizmente, parece que você já tem o link para a pergunta sobre isso.

A volume without a custom icon is going to be displayed with one of the OS's generic icons which you've hard-coded paths to here. A volume with a custom icon is going to store that icon on its filesystem, and if it's not mounted, finding it becomes entirely your job.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top