Na memória de detecção de mime-type com cacau (OS X)?
-
08-07-2019 - |
Pergunta
A minha aplicação é um visualizador para um formato personalizado, um arquivo zip com um manifesto XML bem definido e recursos, como imagens e filmes. Eu uso zlib para abrir o arquivo zip na memória e, em seguida, proceder à visualização disse recursos.
Um problema que eu tive já em é que eu sou incapaz de exibir corretamente vídeos, aparentemente porque QTMovie não pode determinar o tipo MIME. Filme carregado a partir do arquivo ([QTMovie movieWithFile]) funciona perfeitamente. Carregado a partir da memória ([QTMovie movieWithData]) se recusa a trabalhar.
Isso faz sentido, porque falta a extensão do arquivo, QTMovie não pode determinar a informação mime-type. Depois de um pouco de pesquisa, eu recorreu ao uso de QTDataReference na seguinte mannner:
NSData *movieData = ...read from memory...;
QTDataReference *movieDataReference = [[QTDataReference alloc] initWithReferenceToData:movieData name:fileName MIMEType:@"video/x-m4v"];
QTMovie *mov = [QTMovie movieWithDataReference:movieDataReference error:&err];
Isso funciona muito bem, no entanto hardcoding MIMEType está longe de ser ideal. Eu tenho acesso ao nome do arquivo e a extensão, por isso eu tentei encontrar o tipo mime usando UTI (graças aos povos agradáveis ??sobre #macdev):
- (NSString*)mimeTypeForExtension:(NSString*)ext {
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,(CFStringRef)ext,NULL);
return NSMakeCollectable(UTTypeCopyPreferredTagWithClass((CFStringRef)UTI,kUTTagClassMIMEType));
}
Este, porém, não funciona. Claramente, há um banco de dados interno OS X de extensões e correspondentes tipos MIME, em algum lugar. Caso contrário filmes a partir de disco não iria funcionar. Como faço para obter acesso a ele?
Obrigado!
Solução
O problema seu ter é que m4v e m4p não tem um tipo de MIME registrados Launch Services (provavelmente porque o tipo de mime para m4v e m4p não é padrão). Em qualquer caso, o que você provavelmente deve fazer é casos de ponta punho como este e, em seguida, verificar se há nil quando a função retorna (no caso a extensão é tanto não registrado e não tratado por você).
A outra coisa é que você está com vazamento de memória com o seu uso atual. Eu estou supondo que você está usando a coleta de lixo, mas a primeira chamada cria um CFString que nunca é liberado. Aqui está uma implementação sugerida do seu método:
-(NSString*)mimeTypeForExtension:(NSString*)ext
{
NSAssert( ext, @"Extension cannot be nil" );
NSString* mimeType = nil;
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
(CFStringRef)ext, NULL);
if( !UTI ) return nil;
CFStringRef registeredType = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType);
if( !registeredType ) // check for edge case
{
if( [ext isEqualToString:@"m4v"] )
mimeType = @"video/x-m4v";
else if( [ext isEqualToString:@"m4p"] )
mimeType = @"audio/x-m4p";
// handle anything else here that you know is not registered
} else {
mimeType = NSMakeCollectable(registeredType);
}
CFRelease(UTI);
return mimeType;
}
Outras dicas
Você pode usar NSWorkspace ter a UTI palpite sistema de um arquivo.
-(NSString *)mimeTypeForFileAtPath:(NSString *)path error:(NSError **)err {
NSString *uti, *mimeType = nil;
if (!(uti = [[NSWorkspace sharedWorkspace] typeOfFile:path error:err]))
return nil;
if (err)
*err = nil;
if ((mimeType = (NSString *)UTTypeCopyPreferredTagWithClass((CFStringRef)uti, kUTTagClassMIMEType)))
mimeType = NSMakeCollectable(mimeType);
return mimeType;
}
sugerem que as pessoas mudam o retorno à [mimeType autorelease]; - alguns de nós ainda usam as antigas formas
E muito obrigado! Esta foi uma grande ajuda.