Domanda

La mia applicazione è un visualizzatore per un formato personalizzato, un file zip con manifest e risorse XML ben definiti, come immagini e filmati. Uso zlib per aprire il file zip in memoria e quindi procedere per visualizzare tali risorse.

Un problema che ho riscontrato è che non riesco a visualizzare correttamente i video, apparentemente perché QTMovie non è in grado di determinare il tipo mime. Il filmato caricato da file ([QTMovie movieWithFile]) funziona perfettamente. Caricato dalla memoria ([QTMovie movieWithData]) si rifiuta di funzionare.

Questo ha senso, poiché mancando l'estensione del file, QTMovie non è in grado di determinare le informazioni sul tipo MIME. Dopo un po 'di ricerca, ho fatto ricorso all'utilizzo di QTDataReference nel seguente modo:

NSData *movieData = ...read from memory...;
QTDataReference *movieDataReference = [[QTDataReference alloc] initWithReferenceToData:movieData name:fileName MIMEType:@"video/x-m4v"];
QTMovie *mov = [QTMovie movieWithDataReference:movieDataReference error:&err];

Funziona bene, tuttavia MIMEType hardcoding è tutt'altro che ideale. Ho accesso al nome del file e all'estensione, quindi ho provato a trovare il tipo mime usando UTI (grazie alle persone simpatiche su #macdev):

- (NSString*)mimeTypeForExtension:(NSString*)ext {

    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,(CFStringRef)ext,NULL);
    return NSMakeCollectable(UTTypeCopyPreferredTagWithClass((CFStringRef)UTI,kUTTagClassMIMEType));
}

Questo tuttavia non funziona. Chiaramente, c'è un database OS X interno di estensioni e corrispondenti tipi mime, da qualche parte. Altrimenti i film da disco non funzionerebbero. Come posso accedervi?

Grazie!

È stato utile?

Soluzione

Il tuo problema è che m4v e m4p non hanno un tipo mime registrato con Launch Services (probabilmente perché il tipo mime per m4v e m4p non è standard). In ogni caso, ciò che dovresti probabilmente fare è gestire i casi limite come questo e quindi controllare zero quando la funzione ritorna (nel caso in cui l'estensione non sia registrata e non gestita da te).

L'altra cosa è che stai perdendo memoria con il tuo attuale utilizzo. Suppongo che tu stia utilizzando la garbage collection, ma la prima chiamata crea un CFString che non viene mai rilasciato. Ecco un'implementazione suggerita del tuo metodo:

-(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;
}

Altri suggerimenti

È possibile utilizzare NSWorkspace per indurre il sistema a indovinare UTI di un file.

-(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;
}

Suggerisci che le persone cambino il ritorno a [mimeType autorelease]; - alcuni di noi usano ancora gli antichi modi!

E grazie! Questo è stato di grande aiuto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top