iOS是一个监狱,每个第三方 应用都是一个囚徒,其行为完全受到监狱的限制:能做什么,不能做什么,什么时候可以放风,什么时候必须睡觉,甚至生杀予夺,都由监狱说了算。
在这种情况下,多给应用创造点被拜访的机会,无疑对于提高应用的活跃度延长其生命有着重要的意义。
之前我写过一篇iOS开发之Core Spotlight实战。让应用支持 spotlight搜索,当然是让应用放风。让引用支持文档类型以接受其他应用的分享,无疑也是一个机会。
今天稍微花了一点功夫给MarkNote 加上了文件类型支持。其他应用比如mail可以将后缀名为.txt后者.md的文件共享给Marknote。
效果如下:
整个过程不是太复杂。大体分为两步:
- 声明应用所支持的文件类型
- 实现处理的相关代码
下面分开来说。
声明所支持的文件类型
标准文件扩展名
苹果对常用的标准扩展名有一个列表。在这个列表中的文件类型,可以直接根据引用其Identifier。
比如,我的应用需要支持导入txt文件,根据上面提到的列表,找到.txt文件的Identifier为public.plain-text
,直接创建一个types为public.plain-text
的Document type即可。
Document type在Project ->Target -> Info栏中创建。
上图中图标,Name都随意。
非标准扩展名
对于不在上面列表中的文件类型,在进行上面的步骤之前,首先要定义UTI。
比如我要支持的.md后缀就不在上面的列表中,需要定义 UTI。好在定义UTI并不太复杂。
在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>
代码处理
当用户选择我的应用后,iOS会将该文件拷贝到应用的Documents/Inbox目录中,并传给应用该文件路径对应的URL,此URL的scheme是file://。
读取该URL即可得到文件内容。
处理逻辑应该在appdelegate的openURL方法中:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSString *surl = [url absoluteString];
if ([surl hasPrefix:@"file://"]){
// 读到文件内容
NSString* content = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error: nil];
// 处理逻辑略...
// 处理完毕后清理inbox
[self cleanInbox];
}
return YES;
}
处理完文件后,该共享的文件亦然存在Inbox中,应用有义务清理之。清理代码如下:
-(void) cleanInbox{
// 获取应用的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];
}
}
至此文件类型支持功能开发完毕。