0%

扩展名类型判断

在我们使用操作系统,系统通常可以根据文件扩展名/后缀,来判断文件类型,并显示相应图标。那么,iOS 中可以怎样实现呢?

iOS 可以通过 UTI 来进行转换。UTI 是什么呢,用过 Media 相关的框架的同学可能不会陌生。需要了解的同学,可浏览以下资料: - Uniform Type Identifier Concepts - Uniform Type Identifier

具体实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/// extension -> UTI
NSString *UTIForExtension(NSString *extension) {
//Request the UTI via the file extension
NSString *theUTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)(extension), NULL);
return theUTI;
}

/// 匹配 UTI
BOOL extensionConformToUTI(NSString *extension, CFStringRef theUTI) {
NSString *preferredUTI = UTIForExtension(extension);
return (UTTypeConformsTo((__bridge CFStringRef) preferredUTI, theUTI));
}

BOOL extensionLikelyImage(NSString *extension) {
return extensionConformToUTI(extension, CFSTR("public.image"));
}
BOOL extensionLikelyAudio(NSString *extension) {
return extensionConformToUTI(extension, CFSTR("public.audio"));
}
BOOL extensionLikelyMovie(NSString *extension) {
return extensionConformToUTI(extension, CFSTR("public.movie"));
}

🎁彩蛋

顺便的,给出 UTI 与 mimeType 的转换,以及相关的实用函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/// UTI -> mimeType
NSString *mimeTypeForUTI(NSString *aUTI) {
CFStringRef theUTI = (__bridge CFStringRef) aUTI;
CFStringRef mimeType = UTTypeCopyPreferredTagWithClass(theUTI, kUTTagClassMIMEType);
return (__bridge_transfer NSString *)mimeType;
}

/// 元素唯一字典
NSArray *uniqueArray(NSArray *anArray) {
NSMutableArray *copiedArray = [NSMutableArray arrayWithArray:anArray];
for (id object in anArray) {
[copiedArray removeObjectIdenticalTo:object];
[copiedArray addObject:object];
}
return copiedArray;
}

NSArray *conformanceArray(NSString *aUTI) {
NSMutableArray *results = [NSMutableArray arrayWithObject:aUTI];
NSDictionary *dictionary = utiDictionary(aUTI);
id conforms = dictionary[(__bridge NSString *)kUTTypeConformsToKey];

// No conformance
if (!conforms) return results;

// Single conformance
if ([conforms isKindOfClass:[NSString class]]) {
[results addObjectsFromArray:conformanceArray(conforms)];
return uniqueArray(results);
}

// Iterate through multiple conformance
if ([conforms isKindOfClass:[NSArray class]]) {
for (NSString *eachUTI in (NSArray *) conforms)
[results addObjectsFromArray:conformanceArray(eachUTI)];
return uniqueArray(results);
}

// Just return the one-item array
return results;
}

NSArray *allExtensions(NSString *aUTI) {
NSMutableArray *results = [NSMutableArray array];
NSArray *conformance = conformanceArray(aUTI);
for (NSString *eachUTI in conformance) {
NSDictionary *dictionary = utiDictionary(eachUTI);
NSDictionary *extensions = dictionary[(__bridge NSString *)kUTTypeTagSpecificationKey];
id fileTypes = extensions[(__bridge NSString *)kUTTagClassFilenameExtension];

if ([fileTypes isKindOfClass:[NSArray class]])
[results addObjectsFromArray:(NSArray *) fileTypes];
else if ([fileTypes isKindOfClass:[NSString class]])
[results addObject:(NSString *) fileTypes];
}

return uniqueArray(results);
}

NSArray *allMIMETypes(NSString *aUTI) {
NSMutableArray *results = [NSMutableArray array];
NSArray *conformance = conformanceArray(aUTI);
for (NSString *eachUTI in conformance) {
NSDictionary *dictionary = utiDictionary(eachUTI);
NSDictionary *extensions = dictionary[(__bridge NSString *)kUTTypeTagSpecificationKey];
id fileTypes = extensions[(__bridge NSString *)kUTTagClassMIMEType];

if ([fileTypes isKindOfClass:[NSArray class]])
[results addObjectsFromArray:(NSArray *) fileTypes];
else if ([fileTypes isKindOfClass:[NSString class]])
[results addObject:(NSString *) fileTypes];
}

return uniqueArray(results);
}

NSDictionary *utiDictionary(NSString *aUTI) {
NSDictionary *dictionary = (__bridge_transfer NSDictionary *)UTTypeCopyDeclaration((__bridge CFStringRef) aUTI);
return dictionary;
}

欢迎关注我的其它发布渠道