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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章