《iOS 6高级开发手册(第4版)》——2.7节秘诀:使用文档交互控制器

2.7 秘诀:使用文档交互控制器
iOS 6高级开发手册(第4版)
UIDocumentInteractionController类允许应用程序给用户展示一个选项菜单,允许他们以各种方式使用文档文件,利用这个类,用户可以利用以下特性。

iOS应用程序之间的文档共享(即“在某个应用程序中打开这个文档”)。
使用QuickLook进行文档预览。
活动控制器选项,比如打印、共享和社交网络。
你已经在本章前面的动作中见过后两种特性。文档交互类在这些特性顶部添加了应用程序间的共享,如图2-7所示。控制器被展示为菜单,这使用户能够指定他们想怎样与给定的文档交互。

UIDocumentInteractionController显示了用于iPhone(左图)和iPad(右图)的选项风格。两种表示都包括两个页面的图标,如靠近显示屏底部的页面控制器所示

在iOS 6中,“open in”(打开在)选项的数量不再会限制它在早期的OS版本中的使用方式,这就是你为什么会在菜单底部看到页面指示器的原因。用户可以轻扫屏幕,查看“open in”(打开在)选项的完整补充。

控制器提供了两种基本的菜单风格。“open”(打开)风格只提供了“open in”(打开在)选择,使用菜单空间提供尽可能多的目的地选择。“options”(选项)风格(见图2-7)提供了所有交互选项的列表,包括“open in”(打开在)、快速查看和任何支持的动作。它实质上是你将从标准的Actions(“动作”)菜单中获得的所有良好的选项,以及“open in”(打开在)额外选项。你必须明确地添加快速查看回调,但它需要做一点工作。

2.7.1 创建文档交互控制器实例
每个文档交互控制器都特定于单个文档文件。这个文件通常存储在用户的Documents(“文档”)文件夹中:

dic = [UIDocumentInteractionController
    interactionControllerWithURL:fileURL];

你提供一个本地文件URL,并且使用选项变化(基本上是Action菜单)或者打开菜单(仅仅是“open in”(打开在)项目)。两种表示风格都来自于一个栏按钮或者屏幕上的矩形:

presentOptionsMenuFromRect:inView:animated:
presentOptionsMenuFromBarButtonItem:animated:
presentOpenInMenuFromRect:inView:animated:
presentOpenInMenuFromBarButtonItem:animated:

iPad使用你传递的栏按钮或矩形来展示一个弹出窗口(popover)。在iPhone上,实现的功能将展示一个模态控制器视图。如你所期望的,更多的流水账会占据iPad上的空间,其中用户可能点按其他的栏按钮,可能会关闭弹出窗口,等等。

你将希望在展示每个iPad栏按钮项目关联的控制器之后禁用它们,以及在它们不起作用之后重新启用它们。这很重要,因为你不希望用户再次点按正在使用的栏按钮,并且需要处理需要接管不同弹出窗口的情形。基本上,如果不仔细监测哪些按钮是活动的以及哪个弹出窗口正在使用中,将有可能发生各种不愉快的情况。秘诀2-7预防了这些情况。

2.7.2 文档交互控制器属性
每个文档交互控制器都提供了许多属性,可以在你的委托回调中使用它们。

URL属性允许向控制器查询它正在服务的文件,它与你在创建控制器时传递的URL相同。
UTI属性用于确定哪些应用程序可以打开文档。它使用本章前面讨论过的系统提供的功能,基于文件名和元数据查找最佳的UTI匹配。你可以在代码中覆盖它,以手动设置属性。
name属性指定了URL的最后一个路径成分,它提供了一种快捷方式,指定一个用户可解释的名称。
使用icons属性获取正在使用的文件类型的图标。声明支持某些文件类型的应用程序将在它们的声明中提供图像链接(稍后将讨论如何声明文件支持)。这些图像对应于为kUTTypeIconFileKey键存储的值,这在本章前面讨论过。
annotation属性提供了一种方式,连同文件一起把自定义的数据传递给任何将打开该文件的应用程序。这个属性没有标准的用法;尽管如此,仍然必须把项目设置为某个顶级的属性列表对象,即字典、数组、数据、字符串、数字和日期。由于没有共同的标准,人们倾向于把这个属性的使用控制在最小范围内,除非开发人员在他们自己发布的应用程序套件中共享信息。

2.7.3 提供文档Quick Look支持
通过实现3个委托回调给控制器添加Quick Look支持。这些方法声明哪个视图控制器将用于展示预览、哪个视图将宿主它,以及用于预览尺寸的框架。你可能偶尔会有具有说服力的理由,在平板电脑上的有限屏幕空间内使用子视图控制器(比如在拆分视图中,利用仅仅一部分空间进行预览),但是对于iPhone家族,几乎没有任何理由不允许预览占据整个屏幕:

#pragma mark QuickLook
- (UIViewController *)
    documentInteractionControllerViewControllerForPreview:
    (UIDocumentInteractionController *)controller
{
    return self;
}

- (UIView *) documentInteractionControllerViewForPreview:
    (UIDocumentInteractionController *)controller
{
    return self.view;
}

- (CGRect) documentInteractionControllerRectForPreview:
    (UIDocumentInteractionController *)controller
{
    return self.view.frame;
}

2.7.4 检查打开菜单
在使用文档交互控制器时,Options(选项)菜单几乎总会提供有效的菜单选择,尤其是当实现Quick Look回调时。不过,你可能会或者可能不会有任何“open-in”(打开在)选项可以使用。这些选项依赖于你提供给控制器的文件数据以及用户在他们的设备上安装的应用程序。

当设备上没有安装支持你正在使用的文件类型的应用程序时,将会发生没有打开选项的情况。这可能是由于鲜为人知的文件类型引起的,但是更常见的是由于用户还没有购买并安装相关的应用程序。

因此总是要检查是否提供了“Open”(打开)菜单项。秘诀2-7执行了一个相当丑陋的测试,以查看外部程序是否把它们自身提供为给定URL的展示器和编辑器。它的工作方式如下:它创建一个新的、临时的控制器并尝试展示它。如果它获得成功,符合需要的文件目的地就会存在并被安装到设备上。如果没有成功,就没有这样的应用程序,并且应该禁用任何“Open In”(打开在)按钮。

在iPad上,必须在viewDidAppear:中或者以后(也就是说在建立了窗口之后)运行这项检查。方法在展示控制器之后将立即使之消失。最终用户应该不会注意到它,并且没有任何调用使用动画。

显然,这是一个相当糟糕的实现,但它具有在布置界面或者开始处理一个新文件时进行测试的优点。我鼓励你在bugreporter.apple.com上提出一个增强请求。

进一步警告:尽管这种测试可以在主视图上工作(如同这个秘诀中一样),但它可能在iPad上的弹出窗口中的非标准表示中引发问题。

注意:

通常极少在同一个应用程序中同时使用“选项”和“打开”项目。秘诀2-7为Options(选项)菜单使用系统提供的Action(动作)项目。你可能想为只使用“打开”风格的应用程序使用它来代替“Open in...”(打开在)文本。
秘诀2-7 文档交互控制器

@implementation TestBedViewController
{
    NSURL *fileURL;
    UIDocumentInteractionController *dic;
    BOOL canOpen;
}
#pragma mark QuickLook
- (UIViewController *)
    documentInteractionControllerViewControllerForPreview:
        (UIDocumentInteractionController *)controller
{
    return self;
}
- (UIView *) documentInteractionControllerViewForPreview:
(UIDocumentInteractionController *)controller
{
    return self.view;
}
- (CGRect) documentInteractionControllerRectForPreview:
    (UIDocumentInteractionController *)controller
{
    return self.view.frame;
}

#pragma mark Options / Open in Menu

// Clean up after dismissing options menu
- (void) documentInteractionControllerDidDismissOptionsMenu:
    (UIDocumentInteractionController *) controller
{
    self.navigationItem.leftBarButtonItem.enabled = YES;
    dic = nil;
}
// Clean up after dismissing open menu
- (void) documentInteractionControllerDidDismissOpenInMenu:
    (UIDocumentInteractionController *) controller
{
    self.navigationItem.rightBarButtonItem.enabled = canOpen;
    dic = nil;
}

// Before presenting a controller, check to see if there's an
// existing one that needs dismissing
- (void) dismissIfNeeded
{
    if (dic)
    {
        [dic dismissMenuAnimated:YES];
        self.navigationItem.rightBarButtonItem.enabled = canOpen;
        self.navigationItem.leftBarButtonItem.enabled = YES;
    }
}
// Present the options menu
- (void) action: (UIBarButtonItem *) bbi
{
    [self dismissIfNeeded];
    dic = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
    dic.delegate = self;
    self.navigationItem.leftBarButtonItem.enabled = NO;
    [dic presentOptionsMenuFromBarButtonItem:bbi animated:YES];
}
// Present the open-in menu
- (void) open: (UIBarButtonItem *) bbi
{
    [self dismissIfNeeded];
    dic = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
    dic.delegate = self;
    self.navigationItem.rightBarButtonItem.enabled = NO;
    [dic presentOpenInMenuFromBarButtonItem:bbi animated:YES];
}

#pragma mark Test for Open-ability
-(BOOL)canOpen: (NSURL *) aFileURL
{
    UIDocumentInteractionController *tmp =
        [UIDocumentInteractionController
            interactionControllerWithURL:aFileURL];
    BOOL success = [tmp presentOpenInMenuFromRect:CGRectMake(0,0,1,1)
        inView:self.view animated:NO];
    [tmp dismissMenuAnimated:NO];
    return success;
}
- (void) viewDidAppear:(BOOL)animated
{
    // Only enable right button if the file can be opened
    canOpen = [self canOpen:fileURL];
    self.navigationItem.rightBarButtonItem.enabled = canOpen;
}

#pragma mark View management
- (void) loadView
{
    self.view.backgroundColor = [UIColor whiteColor];
    self.navigationItem.rightBarButtonItem =
        BARBUTTON(@"Open in...", @selector(open:));
    self.navigationItem.leftBarButtonItem =
        SYSBARBUTTON(UIBarButtonSystemItemAction,
            @selector(action:));

    NSString *filePath = [NSHomeDirectory()
        stringByAppendingPathComponent:@"Documents/DICImage.jpg"];
    fileURL = [NSURL fileURLWithPath:filePath];
}
@end
时间: 2024-10-26 19:08:44

《iOS 6高级开发手册(第4版)》——2.7节秘诀:使用文档交互控制器的相关文章

《iOS 6高级开发手册(第4版)》——1.4节秘诀:取回额外的设备信息

1.4 秘诀:取回额外的设备信息 iOS 6高级开发手册(第4版) sysctl()和sysctlbyname()允许获取系统信息.这些标准的UNIX函数用于询问操作系统有关硬件和OS的详细信息.看一眼Macintosh上的/usr/include/sys/sysctl.h包括文件,就能对所提供的范围类型有一个感觉.在那里,能够找到一份可以用作这些函数的参数常量的详尽列表. 这些常量使你能够检查核心信息,比如系统的CPU频率.可用的内存量等.秘诀1-2演示了这种功能.它引入了一个UIDevice

《iOS 6高级开发手册(第4版)》——2.8节秘诀:声明文档支持

2.8 秘诀:声明文档支持 iOS 6高级开发手册(第4版) 应用程序文档并不仅限于它们创建或者从Internet下载的文件.如你在前一个秘诀中所发现的,应用程序可能处理某些文件类型.它们可能打开从其他应用程序传递过来的项目.你已经从发送方的角度见过了文档共享,它使用"open in"(打开在)控制器把文件导出到其他应用程序.现在应该从接收方的角度探讨它. 应用程序在它们的Info.plist属性列表中声明它们对某些文件类型的支持.Launch Services(启动服务)系统将读取该

《iOS 6高级开发手册(第4版)》——2.5节秘诀:Quick Look预览控制器

2.5 秘诀:Quick Look预览控制器 iOS 6高级开发手册(第4版) Quick Look预览控制器类允许用户预览许多文档类型.这个控制器支持文本.图像.PDF.RTF.iWork文件.Microsoft Office文档(Office 97及更高版本,包括doc.ppt.xls等)和逗号分隔的值(comma-separated value,csv)文件.你提供一种受支持的文件类型,Quick Look控制器将为用户显示它.集成的系统提供的活动视图控制器有助于共享预览的文档,如图2-6

《iOS 6高级开发手册(第4版)》——2.9节秘诀:创建基于URL的服务

2.9 秘诀:创建基于URL的服务 iOS 6高级开发手册(第4版) Apple的内置应用程序提供了多种可以通过URL调用访问的服务.可以要求Safari打开Web页面,让Maps显示一幅地图,或者使用mailto:风格的URL开始在Mail中撰写一封信件.URL模式指出现在冒号之前的URL的第一部分,比如http或ftp. 这些服务可以工作,因为iOS知道如何将URL模式匹配到应用程序.以http:开头的URL将在Mobile Safari中打开.mailto:URL总会链接到Mail.你可能

《iOS 6高级开发手册(第4版)》——1.2节添加设备能力限制

1.2 添加设备能力限制 iOS 6高级开发手册(第4版) 应用程序的Info.plist属性列表使你能够在向iTunes提交应用程序时指定应用程序的要求.这些限制允许告诉iTunes应用程序需要哪些设备特性. 每个iOS单元都会提供一个独特的特性集.一些设备会提供照相机和GPS能力,另外一些则不会.一些设备具有机载陀螺仪.自动聚焦,以及其他强大的选项.你可以指定在设备上运行应用程序时需要哪些特性. 在Info.plist文件中包括UIRequiredDeviceCapabilities键时,i

《iOS 6高级开发手册(第4版)》——2.3节秘诀:监测Documents文件夹

2.3 秘诀:监测Documents文件夹 iOS 6高级开发手册(第4版) iOS文档并没有受困在它们的沙盒中,你可以并且应该与用户共享它们.应该允许用户直接控制他们的文档,以及访问他们可能在设备上创建的任何资料.一个简单的Info.plist设置将使iTunes能够显示用户的Documents文件夹的内容,并使那些用户能够根据需要添加和删除资料. 在将来某个时间,你可能使用一个简单的NSMetadataQuery监测器来监视Documents文件夹并报告更新.在编写本书时,元数据监视还没有扩

《iOS 6高级开发手册(第4版)》——1.14节跟踪用户

1.14 跟踪用户 iOS 6高级开发手册(第4版) 跟踪是开发者的一种不幸的现实生活.Apple不赞成使用UIDevice属性,该属性提供了绑定到设备硬件的唯一标识符.Apple利用两个标识符属性取代UIDevice属性.它使用identifierForAdvertising属性返回当前设备所独有的一个特定于设备的字符串,并使用identifierForVendor属性提供一个绑定到每位应用程序供应商的字符串.无论使用的是哪个应用程序,这都应该会返回相同的唯一字符串,它不是顾客id.不同设备上

《iOS 6高级开发手册(第4版)》——1.10节秘诀:Core Motion基础

1.10 秘诀:Core Motion基础 iOS 6高级开发手册(第4版) Core Motion框架集中了运动数据处理.该框架是在iOS 4 SDK中引入的,用于取代你刚才阅读到的直接加速计访问.它提供了对3个关键的机载传感器的集中式监测.这些传感器由陀螺仪.磁力计和加速计组成,其中陀螺仪用于测量设备的旋转,磁力计提供了一种测量罗盘方位的方式,加速计用于检测沿着3根轴的重力变化.第四个入口点称为设备移动(device motion),它把全部3种传感器都结合进单个监测系统中. Core Mo

《iOS 6高级开发手册(第4版)》——1.7节同步获取当前的加速计角度

1.7 同步获取当前的加速计角度iOS 6高级开发手册(第4版)有时,你可能想在不用把自己设定为完全委托的情况下查询加速计.下面的方法打算在UIDevice类别内使用,允许与x/y平面(iOS设备的正面)一起同步返回当前的设备角度.为此,可输入一个新的运行循环,等待加速计事件,从那个回调中获取当前的角度,然后让运行循环返回那个角度: - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAccelerati