ios 统一类型标识符

    统一类型标识符是iOS系统在分享信息时所使用的中心组件,可以将他们看成是新一代的MIME类型。UTI是一种字符串,能够表示诸如图像及文本等资源类型。UTI指明了程序之间将要共用的数据对象是何类型。他们并不依赖于原有的各种指示符,比如文件扩展名、MIME类型或是OSType等与文件类型有关的元数据。UTI用一种更新颖、更灵活的技术取代了原有的那些技术。

    UTI的命名遵循反向域名样式。由苹果公司所定义的那些常用标识符,遵循public.html及public.jpeg这样的格式。前者表示HTML原文本,后者表示JPEG图像,这两种UTI都对应于特定类型的信息。

    继承在UTI中扮演了重要角色。UTI使用了与面向对象类似的继承体系,其中的子UTI与上级UTI之间有is-a的关系。子UTI继承了上级UTI的全部属性,此外还添加了一些更为具体的属性,用以体现它所代表的特定信息类型。之所以要这样设计,是因为对于每一个UTI来说,既有比它更通用的UTI,又有比它更具体的UTI。我们以表示JPEG图像的UTI为例来说明。JPEG图像(public.jpeg)是一种图像(public.image),而图像又是一种数据(public.data)。数据是一种用户可以看到或听到的内容(public.content),而内容又表示了一个条目(public.item)。public.item是UTI体系中的通用基础类型。整套体系叫作遵循体系,其中的子UTI”遵循“它的上级UTI。比方说,更为具体的jpeg型UTI就遵循更加通用的image型或data型UTI。

    苹果公司的基本遵循树。树中位置较低的UTI,必须遵循其上级UTI的全部数据属性。如果声明了某个上级UTI,那就表示要支持它的全部子UTI。比方说,如果某程序宣传自己能打开public.data类型的数据,那它就必须能处理文本、电影以及图像文件等内容才行。


    UTI可以多重继承。某个条目可以遵循不止一个上级UTI。所以,我们可以宣传它同时遵循public.text及public.image,这样就能指定一种既能容纳文本又能容纳图像的数据类型了。

    虽说每个UTI都应该遵循命名规范,但却没有统一的UTI注册机构。public域用来表示iOS专用的类型,大部分应用程序都可以共用这些类型。苹果公司生成了一份由public UTI所构成的完整体系图表。

1、根据文件扩展名来决定UTI

    Mobile Core Services模块提供了一些工具,可以根据文件扩展名来获取UTI信息。在使用这些基本C语言的函数之前,必须先引入相关模块。下面这个函数会根据传入的ext字符串参数来返回首选的UTI。返回的这个UTI是一个代表标识符的字符串:

NSString *preferredUTIForExtension(NSString *ext)
{
    NSString *theUTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)ext, NULL);
    return  theUTI;
}

    开发者也可以不传入文件扩展名,而是传入MIME类型,此时UTTypeCreatePreferredIdentifierForTag()的第一个参数应该改为kUTTagClassMiMeType。下面这个函数可以根据给定的MIME类型返回首选的UTI:

NSString *preferredUTIForMIMEType(NSString *mime)
{
    NSString *theUTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)mime, NULL);
    return  theUTI;
}

    开发者可以用上面的这两个函数,把文件名及MIME类型转换成访问文件时经常会用到的UTI类型。


2、把UTI转换成扩展名或MIME类型

    UTTypeCopyPreferredTagWithClass()函数可以把UTI转换成首选扩展名或MIME类型。如果给下面这两个函数传入public.jpeg,那么它们就会分别返回jpeg和image/jpeg:

NSString *extensionForUTI(NSString *aUTI)
{
    CFStringRef theUTI = (__bridge CFStringRef)aUTI;
    CFStringRef results = UTTypeCopyPreferredTagWithClass(theUTI, kUTTagClassFilenameExtension);
    return (__bridge_transfer NSString *)results;
}

NSString *mimeTypeForUTI(NSString *aUTI)
{
    CFStringRef theUTI = (__bridge CFStringRef)aUTI;
    CFStringRef results = UTTypeCopyPreferredTagWithClass(theUTI, kUTTagClassMIMEType);
    return (__bridge_transfer NSString *)results;
}

    使用这两个函数的时候,必须传入树状结构最低端的UTI,也就是与具体的扩展名直接对应的UTI开发者不能只给出上级UTI的类型。扩展名声明在属性列表中,像文件扩展名及默认图标等特征信息,都是在属性列表里描述的。举例来说,开发者如果给extensionForUTI函数传入public.text或public.movie,那么函数会返回nil,但如果传入的是public.plain-text和public.mpeg,则会分别返回txt和mpg。

    前面给出的public.text及public.movie这两个UTI,在整个树状结构中所处的位置太高了,extentsionForUTI函数需要开发者提供更加具体的类型,而不是这种比较抽象的类型。目前并没有API函数能够在抽象的UTI上面找到应用程序中继承自该UTI的所有自条目。读者可以访问bugreport.apple.com,向苹果公司提交这一改进建议。更定有某个地方注册了所有的扩展名和MIME类型,不然的话,UTTypeCopyPreferredTagWithClass()函数怎么能执行转换。

3、判断两个UTI之间是否有依从关系

    UTTypeConformsTo()函数可以判断UTI之间的依从关系。此函数接收两个参数,一个表示待比较的源UTI,另一个表示用于参照的UTI。如果前者遵循后者,那么函数就返回true。通过这个函数,我们可以判断出某个具体的UTI是否遵循另一个宽泛的UTI。UTTypeEqual()函数则可以判断两个UTI是否相等。下面这段范例代码演示了如何判断某个文件路径是否指向图像资源:

BOOL pathPointsToLikelyUTIMatch(NSString *path,CFStringRef theUTI)
{
    NSString *extension = [path pathExtension];
    NSString *preferredUTI = preferredUTIForExtension(extension);
    return UTTypeConformsTo((__bridge CFStringRef)preferredUTI, theUTI);
}

BOOL pathPointsToLikelyImage(NSString *path)
{
    return pathPointsToLikelyUTIMatch(path, CFSTR("public.image"));
}

BOOL pathPointsToLikelyAudio(NSString *path)
{
    return pathPointsToLikelyUTIMatch(path, CFSTR("public.audio"));
}

4、获取依从关系列表

    在iOS的API中,UTTypeCopyDeclaration()可以算是最为通用也最为有用的UTI函数了。它所返回的字典中包含下列键:

    1、kUTTypeIdentifierKey——表示调用者传给函数的UTI名称。

    2、kUTTypeConformsToKey——表示该类型所遵循的上级类型。

    3、kUTTypeDescriptionKey——如果UTI名称还有一种易于理解的描述方式,那么该键所对应的值就是那种描述方式。

    4、kUTTypeTagSpecificationKey——该键对应于一份字典,字典里含有与调用者所传入的UTI等效的OSType、文件扩展名及MIME类型。

    除了上述常用的键之外,还有一些键用于指明导入和导出的UTI声明(kUTImportedTypeDeclarationsKey与kUTExportedTypeDeclarationsKey)、同UTI相关联的图标资源(kUTTypeIconFileKye)、指向该类型描述页面的URL(kUTTypeReferenceURLKey),以及该UTI的版本字符串(kUTTypeVersionKey)。

    开发者可以在UTTypeCopyDeclaration()所返回的字典上面,沿着依从关系树进行遍历,从而构建出一份数组,并且令这份数组能够包含该UTI所遵循的全部上级UTI。比方说,public.mpeg类型的UTI遵循public.movie、public.audiovisualcontent、public.data、public.item、public.content。

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

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 objectForKey:(__bridge NSString *)kUTTypeConformsToKey];
    if (!conforms) {
        return results;
    }
    
    if ([conforms isKindOfClass:[NSString class]]) {
        [results addObjectsFromArray:conformanceArray(conforms)];
        return uniqueArray(results);
    }
    
    if ([conforms isKindOfClass:[NSArray class ]]) {
        for (NSString *eachUTI in conformanceArray(eachUTI)) {
            [results addObjectsFromArray:conformanceArray(eachUTI)];
            
        }
        return uniqueArray(results);
    }
    
    
    return  results;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值