코코아 (OS X)를 사용한 메모리 마임 유형 검출?
-
08-07-2019 - |
문제
내 응용 프로그램은 사용자 정의 형식의 뷰어, 잘 정의 된 XML 매니페스트가있는 ZIP 파일 및 이미지 및 영화와 같은 리소스입니다. Zlib을 사용하여 메모리에서 zip 파일을 열고 상기 자원을 표시합니다.
내가 실행 한 한 가지 문제는 QTMovie가 MIME 유형을 결정할 수 없기 때문에 비디오를 제대로 표시 할 수 없다는 것입니다. 파일에서로드 된 영화 ([qtmovie moviewithfile])가 완벽하게 작동합니다. 메모리에서로드 ([qtmovie moviewithdata])는 작업을 거부합니다.
파일 확장이 없기 때문에 QTMovie는 MIME 유형 정보를 결정할 수 없습니다. 약간의 검색 후, 나는 다음 Mannner에서 qtdatareference를 사용하는 것에 의지했습니다.
NSData *movieData = ...read from memory...;
QTDataReference *movieDataReference = [[QTDataReference alloc] initWithReferenceToData:movieData name:fileName MIMEType:@"video/x-m4v"];
QTMovie *mov = [QTMovie movieWithDataReference:movieDataReference error:&err];
이것은 훌륭하게 작동하지만 하드 코딩 Mimetype은 이상적이지 않습니다. 나는 파일 이름과 확장에 액세스 할 수 있으므로 UTI를 사용하여 마임 유형을 찾으려고 시도했습니다 (#MacDev의 멋진 사람들 덕분).
- (NSString*)mimeTypeForExtension:(NSString*)ext {
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,(CFStringRef)ext,NULL);
return NSMakeCollectable(UTTypeCopyPreferredTagWithClass((CFStringRef)UTI,kUTTagClassMIMEType));
}
그러나 이것은 작동하지 않습니다. 분명히, 내부 OS X 데이터베이스는 확장자와 해당 MIME 유형의 어딘가에 있습니다. 그렇지 않으면 디스크에서 영화가 작동하지 않습니다. 어떻게 접근 할 수 있습니까?
감사!
해결책
당신이 가진 문제는 M4V와 M4P에 런칭 서비스에 등록 된 MIME 유형이 없다는 것입니다 (아마도 M4V 및 M4P의 MIME 유형이 표준이 아니기 때문일 것입니다). 어쨌든, 아마도 당신이해야 할 일은 이와 같은 에지 케이스를 처리 한 다음 함수가 반환 될 때 NIL을 확인하는 것입니다 (확장자가 등록되지 않고 처리되지 않은 경우).
다른 하나는 현재 사용으로 메모리를 새는 것입니다. 나는 당신이 쓰레기 수집을 사용하고 있다고 가정하지만 첫 번째 호출은 출시되지 않은 CFString을 만듭니다. 다음은 제안 된 방법의 구현입니다.
-(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;
}
다른 팁
nsworkspace를 사용하여 파일의 시스템 추측 UTI를 사용할 수 있습니다.
-(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;
}
사람들이 [Mimetype AutoreLease]로 돌아가는 것을 제안합니다. - 우리 중 일부는 여전히 고대 방식을 사용합니다!
그리고 고마워! 이것은 큰 도움이되었습니다.