《iOS 6高级开发手册(第4版)》——2.8节秘诀:声明文档支持
本节书摘来自异步社区《iOS 6高级开发手册(第4版)》一书中的第2章,第2.8节秘诀:声明文档支持,作者 【美】Erica Sadun,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.8 秘诀:声明文档支持
iOS 6高级开发手册(第4版)
应用程序文档并不仅限于它们创建或者从Internet下载的文件。如你在前一个秘诀中所发现的,应用程序可能处理某些文件类型。它们可能打开从其他应用程序传递过来的项目。你已经从发送方的角度见过了文档共享,它使用“open in”(打开在)控制器把文件导出到其他应用程序。现在应该从接收方的角度探讨它。
应用程序在它们的Info.plist属性列表中声明它们对某些文件类型的支持。Launch Services(启动服务)系统将读取该数据,并创建被文档交互控制器使用的文件-应用程序之间的关联。
尽管可以直接编辑属性列表,但是Xcode 4提供了一种简单的形式,作为Project > Target > Info screen的一部分。定位Document Types区域,你将发现它位于Custom iOS Target Properties下面。打开这个区域,并单击“+”,添加受支持的新文档类型。图2-8显示了它对于接受JPEG图像文档的应用程序来说看起来像是什么样子的。
这个声明包含3个最低限度的细节:名称、一个或多个UTI以及一个处理程序等级,在这里是替代者。
名称是必需的和任意的。它应该能够描述正在使用的文档的种类,但它在iOS上也有点像是一种事后追加的东西。当在Macintosh上使用时这个字段将更有意义(它是Finder使用的“种类”字符串),但它不是可选的。
在输入时指定一个或多个UTI。这个示例只指定了public.jpeg。在列出多个项目时,可以在项目之间添加逗号。例如,你可能具有一种打开public.jpeg、public.tiff和public.png的“图像”文档类型。当需要限制文件支持时,可以枚举特定的类型。尽管声明public.image将包含全部3种类型,它也可能允许打开不受支持的图像样式。
启动服务处理程序等级描述了应用程序如何在处理这种文件类型的竞争中看待它自身。“所有者”说这是创建这类文件的原始应用程序,“替代者”(如图2-8所示)则提供了辅助的查看方式。可以在额外的文档类型属性中手动添加LSHandlerRank键。
可以选择指定图标文件。它们在OS X中被用作文档图标,与iOS世界具有最少的重叠。在唯一一种情况下,我可以认为你可能把这些图标看作iTunes中的Apps选项卡,此时将使用File Sharing区域添加和移除项目。图标通常具有两种尺寸:320像素×320像素(UTType Size320IconFile)和64像素×64像素(UTTypeSize64IconFile),通常限制于应用程序创建并为其定义一种自定义类型的文件。
Xcode在底下使用这种交互形式在应用程序的Info.plist中构建一个CFBundleDocumentTypes数组。下面的代码段以其Info.plist形式显示了图2-8中的信息。
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFiles</key>
<array/>
<key>CFBundleTypeName</key>
<string>jpg</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.jpeg</string>
</array>
</dict>
</array>
2.8.1 创建自定义的文档类型
当应用程序构建新的文档类型时,应该在Target > Info编辑器的Exported UTIs区域中声明它们,如图2-9所示。这将注册系统支持这种文件类型,并把你标识为该类型的所有者。
编辑器的Exported UTIs区域中声明自定义的文件类型
要定义新的类型,可以提供一个自定义的UTI(在这里是com.sadun.cookbookfile)、文档艺术作品(大小为64像素和320像素),并且指定标识文件类型的文件扩展名。与声明文档支持一样,Xcode将把一个导出的声明数组构建到项目的Info.plist文件中。下面显示了图2-9中所示的声明看起来可能像是什么样子的。
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.text</string>
</array>
<key>UTTypeDescription</key>
<string>Cookbook</string>
<key>UTTypeIdentifier</key>
<string>com.sadun.cookbookfile</string>
<key>UTTypeSize320IconFile</key>
<string>Cover-320</string>
<key>UTTypeSize64IconFile</key>
<string>Cover-64</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>cookbook</string>
</dict>
</dict>
</array>
如果像这样添加到项目中,应用程序应该会使用com.sadun.cookbookfile UTI,打开具有cookbook扩展名的任何文件。
2.8.2 实现文档支持
当应用程序提供了文档支持时,每当“Inbox”(收件箱)文件夹变成活动状态时都应该检查它。确切地讲,查看Inbox文件夹是否出现在Documents文件夹中。如果是,就应该把那个收件箱中的元素移到属于它们的位置,通常是在主Documents目录中。在清空了收件箱后,就删除它。这提供了最佳的用户体验,尤其对于通过iTunes进行任何文件共享则更是如此,其中的Inbox及其作用可能使用户混淆:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// perform inbox test here
}
当把项目移到Documents中时,要检查名称冲突,并且使用替代路径名称(通常是通过追加一个连字符,其后接着一个数字)来避免重写任何现有的文件。下面的方法有助于查找目标路径的替代名称。在经过1000次尝试后,它会放弃,但是严重的是,任何用户都不应该宿主许多重复的文档名称。如果他们这样做,总体应用程序设计就会存在严重的错误。
秘诀2-8展示了扫描Inbox并把文件移到合适位置的细节。它将在清空Inbox之后移除它。可以看到,任何像这样的方法都是文件管理器密集型的。它主要涉及处理可能在整个任务过程中弹出的各种可能的错误组合,这对于小文件支持应该运行得很快。如果必须处理大文件,比如视频或音频,就要确保在它自己的操作队列上执行这种处理。
如果计划支持public.data文件(也就是说,将打开任何内容),则可能希望使用UIWebView实例显示那些文件。参阅Technical Q&A QA1630(http://developer.apple.com/library/ios/#qa/qa1630),可了解关于iOS在那些视图中能够以及不能显示哪些文档类型的详细信息。Web视图可以展示大多数音频和视频资源,以及Excel、Keynote、Numbers、Pages、PDF、PowerPoint和Word资源,还包括简单的HTML。
秘诀2-8 处理传入的文档
#define DOCUMENTS_PATH [NSHomeDirectory() \
stringByAppendingPathComponent:@"Documents"]
#define INBOX_PATH [DOCUMENTS_PATH \
stringByAppendingPathComponent:@"Inbox"]
@implementation InboxHelper
+ (NSString *) findAlternativeNameForPath: (NSString *) path
{
NSString *ext = path.pathExtension;
NSString *base = [path stringByDeletingPathExtension];
for (int i = 1; i < 999; i++)
{
NSString *dest =
[NSString stringWithFormat:@"%@-%d.%@", base, i, ext];
// if the file does not yet exist, use this destination path
if (![[NSFileManager defaultManager]
fileExistsAtPath:dest])
return dest;
}
NSLog(@"Exhausted possible names for file %@. Bailing.",
path.lastPathComponent);
return nil;
}
- (void) checkAndProcessInbox
{
// Does the Inbox exist? If not, we're done
BOOL isDir;
if (![[NSFileManager defaultManager]
fileExistsAtPath:INBOX_PATH isDirectory:&isDir])
return;
NSError *error;
BOOL success;
// If the Inbox is not a folder, remove it.
if (!isDir)
{
success = [[NSFileManager defaultManager]
removeItemAtPath:INBOX_PATH error:&error];
if (!success)
{
NSLog(@"Error deleting Inbox file (not directory): %@",
error.localizedFailureReason);
return;
}
}
// Retrieve a list of files in the Inbox
NSArray *fileArray = [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:INBOX_PATH error:&error];
if (!fileArray)
{
NSLog(@"Error reading contents of Inbox: %@",
error.localizedFailureReason);
return;
}
// Remember the number of items
NSUInteger initialCount = fileArray.count;
// Iterate through each file, moving it to Documents
for (NSString *filename in fileArray)
{
NSString *source =
[INBOX_PATH stringByAppendingPathComponent:filename];
NSString *dest = [DOCUMENTS_PATH
stringByAppendingPathComponent:filename];
// Is the file already there?
BOOL exists =
[[NSFileManager defaultManager] fileExistsAtPath:dest];
if (exists) dest = [self findAlternativeNameForPath:dest];
if (!dest)
{
NSLog(@"Error. File name conflict not resolved");
continue;
}
// Move file into place
success = [[NSFileManager defaultManager]
moveItemAtPath:source toPath:dest error:&error];
if (!success)
{
NSLog(@"Error moving file from Inbox: %@",
error.localizedFailureReason);
continue;
}
}
// Inbox should now be empty
fileArray = [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:INBOX_PATH error:&error];
if (!fileArray)
{
NSLog(@"Error reading contents of Inbox: %@",
error.localizedFailureReason);
return;
}
if (fileArray.count)
{
NSLog(@"Error clearing Inbox. %d items remain",
fileArray.count);
return;
}
// Remove the inbox
success = [[NSFileManager defaultManager]
removeItemAtPath:INBOX_PATH error:&error];
if (!success)
{
NSLog(@"Error removing inbox: %@",
error.localizedFailureReason);
return;
}
NSLog(@"Moved %d items from the Inbox", initialCount);
}
@end
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
《Cisco IOS XR技术精要》一2.6 Cisco IOS XR系统数据库
本节书摘来自异步社区《Cisco IOS XR技术精要》一书中的第2章,第2.6节,作者 【美】Mobeen Tahir , Mark Ghattas , Dawit Birhanu , Syed Natif Nawaz,更多章节内容可以访问云栖社区“异步社区”公众号查看 2.6 Cisco IOS XR系统数据库 Cisco IOS XR技术精要由于IOS XR是为大型分布式系统而设计的,因此,在配置和可操作数据上,使用一种分布式的数据存储机制是至关重要的。在IOS XR中,一套系统包括一台或多台安全域路由器(SDR)。每块LC或RP只能关联到一台SDR上。不过,SDR可以共享某些常用硬件组件,包括机框、电源、风扇、风扇控制器,以及矩阵卡。 Cisco IOS XR系统数据库(SysDB)为应用提供了如储存、修改、访问系统信息等常见机制。SysDB通过层次性的命名空间构建了完全分布的内存数据存储。这是通过将SysDB命名空间分割成admin(管理)、shared(共享)和local(本地)三个独立平面来实现的。每个SysDB服务器进程只与共享平面、本地平面或管理平面其中的某个精确地相...
-
下一篇
《深入解析Android 虚拟机》——导读
本节书摘来自异步社区《深入解析Android 虚拟机》一书中的目录,作者 钟世礼,更多章节内容可以访问云栖社区“异步社区”公众号查看 目 录前 言 第1章 获取并编译Android源码第1章第1.1节获取Android源码第1章第1.2节分析Android源码结构第1章第1.3节编译Android源码第1章第1.4节编译Android Kernel 第2章 Java虚拟机基础 第2章第2.1节虚拟机的作用第2章第2.2节Java虚拟机概述第2章第2.3节JVM的安全性第2章第2.4节网络移动性第2章第2.5节内存异常和垃圾处理第2章第2.6节Java内存模型第3章 Dalvik和ART基础第4章 分析JNI第5章 分析内存系统第6章 Android程序的生命周期管理第7章 IPC进程通信机制第8章 init进程详解第9章 Dalvik VM的进程系统第10章 Dalvik VM运作流程详解第11章 DEX文件详解第12章 Dvlik VM内存系统详解第13章 Dalvik VM垃圾收集机制第14章 Dalvik VM内存优化机制详解第15章 分析Dalvik VM的启动过程第16章 注...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Crontab安装和使用
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,7,8上安装Nginx,支持https2.0的开启

微信收款码
支付宝收款码