iOS,在应用之间共享文档

在iOS开发中,在很多情况下我们需要完成应用之间的文档共享。然而,iOS为应用提供的是一个运行沙箱,一个应用程序无法直接和另一个应用程序通讯,所以应用之间如果要共享文档的话需要通过一些系统提供的应用交互手段。

iOS应用程序之间交互的一个简单手段是“URL Scheme”,就是通过UIApplication的openURL方法,使用“<应用名>://”这样的URL形式指定应用,同时可以在URL中加入一些类似于http的get请求的参数,用于传递简单数据,代码样例如下:

 [[ UIApplication   sharedApplication openURL :[ NSURL   URLWithString : @"myapp://test_page/one?token=12345&user=ABC"  ]];

以上代码会启动应用“myapp”,然后传递参数token和user给应用myapp。
不过这种应用调用无法完成应用间文档共享,这能完成一些简单的数据传递。有关“URL Scheme”的具体使用可以参考iOS官方样例中的LaunchMe。

为了给其它应用程序共享文档,发起共享的应用一般使用的是UIDocumentInteractionController类,通过调用该类实例的presentOpenInMenuFromRect方法显示一个“OpenIn”菜单,该菜单中会显示系统中声明可以支持你所共享的文档的应用图标,由用户选择使用那个应用打开你共享的应用。

下面是一段代码样例,该样例通过UIDocumentInteractionController的interactionControllerWithURL方法创建了一个UIDocumentInteractionController实例,然后调用该实例的 presentOpenInMenuFromRect方法显示“OpenIn”菜单。

NSString *filePath =

    [[NSBundlemainBundle]

     pathForResource:@"PDF Document"ofType:@"pdf"];

    

    NSLog(@"file path is: %@", filePath);

    

    

    self.documentController =

    [UIDocumentInteractionController

     interactionControllerWithURL:[NSURLfileURLWithPath:filePath]];

    self.documentController.delegate =self;

   

    self.documentController.UTI =@"com.adobe.pdf";

    [self.documentControllerpresentOpenInMenuFromRect:CGRectZero

                                          inView:self.view

                                        animated:YES];

将以上代码放置到一个控件对应的action方法中,触发该控件就会让系统弹出“OpenIn”菜单,有用户选者使用什么程序打开你所共享的应用。
注意,在“OpenIn”菜单中会出现所有声称支持对应文档类型的应用,比如上例中的“OpenIn”菜单中会出现所有“声称”支持pdf格式的应用图标,至于用户选择哪个应用,所选择的应用是否真的可以正常处理pdf文档是我们无法控制的。


为了使用其它应用程序共享的文档,接受文档的应用需要完成两个工作。
第一个工作是在应用的Info.plist中加入声明,声明该程序支持什么文档格式。比如你需要支持pdf文档,就可以在你的应用项目配置界面选择“Info”页面的“Document types”区段,在里面加入pdf文档类型的配置,如下图:

iOS,在应用之间共享文档_第1张图片

第二个工作是接受其它程序共享的数据,正常做法是在应用的openURL方法中加入响应代码,在该代码中去访问参数URL中纪录的文档,该URL指向本应用Documents目录中的inbox目录中的一个文件,该文件就是其它程序共享的文档的一个拷贝。具体代码如下:


- (BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation


{

    NSLog(@"openURLmethod was called");

    

    NSLog(@"the source application is: %@", sourceApplication);

    

    

    NSLog(@"url is: %@", url);

    

    NSLog(@"handle the file in above file path for the shared doc");

    

    

    return YES;

}


以上openURL方法通过控制台打印了打印了共享文档的应用名称和所共享的文档在本应用中的访问路径,通过这个访问路径开发人员可以在本应用中访问到其它应用所共享的文档。


实现itunes可以上传文件到应用
用程序可以使用文件共享让用户访问程序的用户数据文件。文件共享允许应用程序通过iTunes向用户显露应用程序 /Documents目录的内容。这样,用户就可以在iPad和桌面计算机来回移动文件。但是,该功能不允许应用程序和同一设备上的其他应用程序共享文件。如果希望在程序间共享文件,请使用剪贴板或者文档交互控制器对象。

您可以通过如下步骤来让应用程序支持文件共享:

  1. 在应用程序的Info.plist文件中添加UIFileSharingEnabled键,并将键值设置为YES

  2. 将您希望共享的文件放在应用程序的Documents目录。

  3. 一旦设备插入到用户计算机,iTunes 9.1就会在选中设备的Apps标签中显示一个File Sharing区域。

  4. 此后,用户就可以向该目录添加文件或者将文件移动到桌面计算机中。

如果应用程序支持文件共享,当文件添加到Documents目录后,应用程序应该能够识别并做出适当响应。例如说,应用程序可以将新文件的内容显示界面上。请不要向用户展现目录的文件列表并询问他们希望对文件执行什么操作。

补充

IOS的文件系统面向的是设备上的每个运行的应用程序。为了保证IOS系统的可用性和简单性,IOS设备的终端用户是无法直接访问文件系统的,同时设备上的app与用户一样也是不能随便直接访问文件系统的。IOS的app与文件系统之间的交互被限定在了一个指定的空间或者说是一个目录里,该目录存在于每个App自身沙箱(sandbox)内部。每当在IOS设备上安装一个新的app,IOS的设备上的程序安装器会自动为这个新app提供一个主目录(Home Directory),并将app安装在为其创建的主目录下,此外安装器还会创建为app创建其它几个关键性的目录。所有这些创建的目录组合起来就组成了app的文件系统主视图。因此app对文件系统的操作也仅限定在了以上目录的组合,app可以直接读取这些目录及目录下的任何文件,同时app也可以在指定的任何目录创建自己的文件或写入自己的数据。翻过来说,在这个指定范围之外app不能再访问或创建任何目录和文件。比较特殊的情况是,IOS系统会提供系统接口来允许app访问,例如访问用户存储在设备上的联系方式,相册。但访问这些内容背后所对应的文件操作都是由底层的系统框架来完成。这也是app被称为是一个“沙箱”的原因,在自己的沙箱内,app拥有全面的操作控制权;沙箱之外的东西,在有悖访问规则的前提下,app不能做任何事情。

开启iTunes文件共享
       之前对Linux/Unix系统不熟悉(现在其实也不熟悉),对苹果的设备环境,开发体系,硬件特点基本上也处于无知状态,记得起初拿到iPad的时候,一直以为作为移动设备,既然iPad能够与PC端连接,那么就可以把它同时当做是一个移动硬盘来用,可以在PC可iPad之间进行文件的传输,存储,共享。我可以想任意App中放置文件,也可以在PC端像浏览Mac上的文件系统一样,去查看App目录下的内容。后来我发现我错了,根本不是想象中的那样。当iPad连接PC之后,并没有一个设备目录浏览管理界面。其实这也比较苹果系统封闭的风格,苹果希望将用户在苹果设备上的文件都能上传到云端,从而实现可以在多台苹果设备上同步用户数据。

       通过在app工程的Info.plist文件中指定UIFileSharingEnabled关键字,并将其值设置为YES。我们可以很方便的打开app与iTunes之间的文件共享。但这种共享有一个前提:App必须将任何所需要共享给用户的文件,都要存放在<Application_Home>/Documents目录下,<Application_Home>即在app安装时自动创建的app的主目录。下面我们简单说明

在MAC上打开iTunes,在应用程序一栏,默认界面为:
iOS,在应用之间共享文档_第2张图片

当链接iPad设备后,iTunes界面如下,在面板工具条的右侧会显示iPad当前已连接到Mac上

iOS,在应用之间共享文档_第3张图片

      点击工具条的"iPad"按钮,显示具体的iPad设备信息,如下:

iOS,在应用之间共享文档_第4张图片

     被黄色块盖住的是iPad的设备名称,点击“应用程序按钮”,之后在界面上我们可以看到当前iPad设备的一些相关分类信息,包括存储空间大小,iPad上所安装的IOS版本,是否存在可升级的更高版本的IOS;以及一些iPad设备的备份方式。继续下滚屏,如下界面:

iOS,在应用之间共享文档_第5张图片


      我们看到出现了一个名为“文件共享”的分类。上面很清楚的标明了这个分类的作用是什么,左侧的列表是iPad设备上安装的所有应用程序,右侧列表则是支持iTunes文件共享的App的Documents目录。以苹果的Keynote为例,当我们保存一个文档到iTunes时,Keynotye会讲文件写入到自己的Documents目录下,也就是我们在面板上看到的右侧列表。我们可以直接从MAC上拖文件到该右侧列表,或者从右侧列表选中文件直接拖到MAC上,这样便简单的完成了所谓的iTunes与App的文件共享。可以通过两个按钮完成同样的功能。如图:

iOS,在应用之间共享文档_第6张图片

      我们新建一个简单的DEMO工程来把整个流程走一遍,工程名为FileShareWithITunesDemo

iOS,在应用之间共享文档_第7张图片

     在工程的Info.plist文件中添加支持iTunes文件共享的Key,并将值设为YES,

iOS,在应用之间共享文档_第8张图片

     之后将DEMO工工程发布到iPad设备上,在iTunes的面板上我们可以看到如下图:

iOS,在应用之间共享文档_第9张图片

       现在左侧列表中有了我们的工程对应的APP,接下来在mainStoryboard中添加简单的描述和两个按钮:

iOS,在应用之间共享文档_第10张图片

      之后为两个按钮建立action的outline,代码如下

01 // 对应第一个按钮
02 - (IBAction)logFilePathInDocumentsDir:(id)sender
03 {
04     NSString *docsDir = [NSHomeDirectory() stringByAppendingPathComponent:  @"Documents"];
05      
06     NSFileManager *fileManager = [NSFileManager defaultManager];
07      
08     NSDirectoryEnumerator *dirEnum = [fileManager enumeratorAtPath:docsDir];
09      
10     NSString *fileName;
11      
12     while (fileName = [dirEnum nextObject]) {
13         NSLog(@"FielName : %@" , fileName);
14         NSLog(@"FileFullPath : %@" , [docsDir stringByAppendingPathComponent:fileName]) ;
15     }
16  
17 }
18 // 对应第二个按钮
19 - (IBAction)createImageFieldToDocuments:(id)sender
20 {
21     NSFileManager *fileManager=[[NSFileManager alloc] init];
22      
23     NSString *docsDir = [NSHomeDirectory() stringByAppendingPathComponent: @"Documents"];
24      
25     NSString *imageFileName = [docsDir stringByAppendingPathComponent:@"myImage.png"] ;
26      
27     UIImage *image = [self generateImage];
28      
29     [fileManager createFileAtPath:imageFileName contents:UIImagePNGRepresentation(image) attributes:nil] ;
30      
31 }
32 // 创建一个简单的UIImage对象并作为图片文件内容
33 - (UIImage*)generateImage
34 {
35     UIGraphicsBeginImageContextWithOptions(CGSizeMake(320, 200), NO, 0.0) ;
36      
37     CGContextRef ctx = UIGraphicsGetCurrentContext() ;
38      
39     CGRect imageRect = CGRectMake(0.0, 0.0, 320, 200) ;
40      
41     [[UIColor redColor] setFill] ;
42      
43     CGContextFillRect(ctx, imageRect) ;
44      
45     UIImage *image = UIGraphicsGetImageFromCurrentImageContext() ;
46      
47     UIGraphicsEndImageContext() ;
48      
49     return image ;
50 }

       我们先从MAC简单的拖张图片文件到右侧列表,如图示:

iOS,在应用之间共享文档_第11张图片

     之后点击第一个按钮,输出Documents路径下的所有文件名到控制台


iOS,在应用之间共享文档_第12张图片


      完成之后,点击第二个按钮完成向Documents目录保存文件的功能(即共享文件到iTunes)

iOS,在应用之间共享文档_第13张图片

至此,简单的流程完毕。

注:描述于IOS6.1下

你可能感兴趣的:(iOS,在应用之间共享文档)