iOS是一個監(jiān)獄,每個第三方 應(yīng)用都是一個囚徒,其行為完全受到監(jiān)獄的限制:能做什么,不能做什么,什么時候可以放風(fēng),什么時候必須睡覺,甚至生殺予奪,都由監(jiān)獄說了算。
在這種情況下,多給應(yīng)用創(chuàng)造點(diǎn)被拜訪的機(jī)會,無疑對于提高應(yīng)用的活躍度延長其生命有著重要的意義。
之前我寫過一篇iOS開發(fā)之Core Spotlight實(shí)戰(zhàn)。讓應(yīng)用支持 spotlight搜索,當(dāng)然是讓應(yīng)用放風(fēng)。讓引用支持文檔類型以接受其他應(yīng)用的分享,無疑也是一個機(jī)會。
今天稍微花了一點(diǎn)功夫給MarkNote 加上了文件類型支持。其他應(yīng)用比如mail可以將后綴名為.txt后者.md的文件共享給Marknote。
效果如下:
整個過程不是太復(fù)雜。大體分為兩步:
- 聲明應(yīng)用所支持的文件類型
- 實(shí)現(xiàn)處理的相關(guān)代碼
下面分開來說。
聲明所支持的文件類型
標(biāo)準(zhǔn)文件擴(kuò)展名
蘋果對常用的標(biāo)準(zhǔn)擴(kuò)展名有一個列表。在這個列表中的文件類型,可以直接根據(jù)引用其Identifier。
比如,我的應(yīng)用需要支持導(dǎo)入txt文件,根據(jù)上面提到的列表,找到.txt文件的Identifier為public.plain-text,直接創(chuàng)建一個types為public.plain-text的Document type即可。
Document type在Project ->Target -> Info欄中創(chuàng)建。
上圖中圖標(biāo),Name都隨意。
非標(biāo)準(zhǔn)擴(kuò)展名
對于不在上面列表中的文件類型,在進(jìn)行上面的步驟之前,首先要定義UTI。
比如我要支持的.md后綴就不在上面的列表中,需要定義 UTI。好在定義UTI并不太復(fù)雜。
在Project ->Target -> Info欄中找到Imported UTI,添加一個,定義如下:
聲明完UTI后就可以直接在Document Type中直接用了:
以上操作也可以直接在App的info.plist文件中直接用寫。比如我的UTI聲明部分:
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.text</string>
</array>
<key>UTTypeDescription</key>
<string>markdown document</string>
<key>UTTypeIdentifier</key>
<string>public.markdown</string>
<key>UTTypeSize320IconFile</key>
<string>IconLite</string>
<key>UTTypeSize64IconFile</key>
<string>IconLite</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>md</string>
<string>MD</string>
<string>markdown</string>
</array>
</dict>
</dict>
</array>
文檔類型部分:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFiles</key>
<array>
<string>IconLite</string>
</array>
<key>CFBundleTypeName</key>
<string>Plain text</string>
<key>LSItemContentTypes</key>
<array>
<string>public.plain-text</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFiles</key>
<array>
<string>IconLite</string>
</array>
<key>CFBundleTypeName</key>
<string>Markdown document</string>
<key>LSItemContentTypes</key>
<array>
<string>public.markdown</string>
</array>
</dict>
</array>
代碼處理
當(dāng)用戶選擇我的應(yīng)用后,iOS會將該文件拷貝到應(yīng)用的Documents/Inbox目錄中,并傳給應(yīng)用該文件路徑對應(yīng)的URL,此URL的scheme是file://。
讀取該URL即可得到文件內(nèi)容。
處理邏輯應(yīng)該在appdelegate的openURL方法中:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSString *surl = [url absoluteString];
if ([surl hasPrefix:@"file://"]){
// 讀到文件內(nèi)容
NSString* content = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error: nil];
// 處理邏輯略...
// 處理完畢后清理inbox
[self cleanInbox];
}
return YES;
}
處理完文件后,該共享的文件亦然存在Inbox中,應(yīng)用有義務(wù)清理之。清理代碼如下:
-(void) cleanInbox{
// 獲取應(yīng)用的Document目錄
NSString *documentsDirectory = [FileUtil documentPath];
// 分享過來的文件都在Inbox子目錄下
NSString *path = [NSString stringWithFormat:@"%@/Inbox", documentsDirectory ];
NSArray *directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
for (NSString *file in directoryContents) {
NSString* fullPath = [NSString stringWithFormat:@"%@/%@", path,file ];
[FileUtil removeFile:fullPath];
}
}
至此文件類型支持功能開發(fā)完畢。