注册你app所支持的文件类型以及Document interaction案例

来源:互联网 发布:java接收json 编辑:程序博客网 时间:2024/05/21 10:53

概要点:

1. 你要注册(向ios/mac系统)申明app能够打开某种类型的文档,这样其他app才可能通过DIC(document interaction interface)把文件转给你app来打开

2. 注册就要在plist里声明: document types(我猜的),然后打开文本模式一看,果然对应了CFBundleDocumentTypes



<key>CFBundleDocumentTypes</key>

<array>

<dict>

<key>CFBundleTypeName</key>文档类型名称

<string>pdf</string>

<key>LSHandlerRank</key> //是拥有此类型文档,还是仅用于打开

<string>Default</string>

</dict>

</array>

一般而言一个文档类型和一个文件类型对应,当然也可以是多个文件类型例如。doc/。docx是word文档在两个不同版本下的文件后缀。这样你可以把这两个文件类型组合在一个文档类型中

A uniform type identifier (UTI) is a string that identifies a class of entities with a type. UTIs are typically used to identify the format for files or in-memory data types and to identify the hierarchical layout of directories, volumes or packages

这里有个基本的对照表,文件后缀和UTI的串

https://developer.apple.com/library/mac/#documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html

更多的对应可以参考:

 Apple's Uniform Type Identifiers Overview

<key>LSItemContentTypes</key>        <array>            <string>com.sunsetlakesoftware.molecules.pdb</string> //app id+.pdb            <string>org.gnu.gnu-zip-archive</string>        </array>
这里我们使用了一个系统定义的。org。gnu。。。。另外一个是程序定义的UTI,程序定义的UTI需要导出,系统其他程序才能知道//

3. 需要为自定义的UtI在plist中申明:

<key>UTExportedTypeDeclarations</key><array>    <dict>        <key>UTTypeConformsTo</key>        <array>            <string>public.plain-text</string>            <string>public.text</string>        </array>        <key>UTTypeDescription</key>        <string>Molecules Structure File</string>        <key>UTTypeIdentifier</key>        <string>com.sunsetlakesoftware.molecules.pdb</string> // 自定义的type identifier        <key>UTTypeTagSpecification</key>        <dict>            <key>public.filename-extension</key> //关键点            <string>pdb</string>            <key>public.mime-type</key>  //关键点            <string>chemical/x-pdb</string>        </dict>    </dict></array>
关键是说明com.sunsetlakesoftware.molecules.pdb UTI 是和.pdb后缀文件关联,且mime类型是 chemical/x-pdb.

这样一来,在邮件程序中,tap且hold等待弹出候选程序列表,可以打开特定的文件。

当附件被打开,你的app就启动了。一般而言,至少要在application:didfinishelaunchingwithoptions中处理文件路径等,看起来就像是文件被copy到你app目录下,然后打开了:

NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];



再看另外一个例子,注释在其中

<dict>
   <key>CFBundleTypeName</key>
   <string>My File Format</string> //任意定义
   <key>CFBundleTypeIconFiles</key>  //icon图标资源,当用于显示此类文件的时候
       <array>
           <string>MySmallIcon.png</string>  //resource in bundle
           <string>MyLargeIcon.png</string>
       </array>
   <key>LSItemContentTypes</key>  //使用了UTI格式的,关联到文件格式
       <array>
           <string>com.example.myformat</string> //
       </array>
   <key>LSHandlerRank</key>
   <string>Owner</string> //非默认,而是owner
</dict>

也可以通过MIME来指定文件类型


CFBundleTypeMIMETypes

"Document MIME types”

Array

Contains an array of strings. Each string contains the MIME type name you want to map to this document type. (In Mac OS X v10.4, this key is ignored if the LSItemContentTypeskey is present.) Deprecated in Mac OS X v10.

更多信息:

https://developer.apple.com/library/ios/#documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-SW1


案例: 在iOS app中导入/导出文档

我们经常会用到的文件操作,又希望本地有文档保存,可以离线操作,其实ibook/iannotation之类多有类似的东西,就是本地library;有时候,还希望可以导出文件去另g外一个地方:

新建一个项目view based application:

打开nib文件,增加两控件:

  • WebView/
  • Round Rect Button

  • 1. 通过拖拽,完成outlet /action的声明;增加一些message例如opendocument/handledocumentopenUrL/

    2.注意到要实现protocol:UIDocumentInteractionControllerDelegate

  • @interface flyViewController : UIViewController<UIDocumentInteractionControllerDelegate>{    IBOutlet UIWebView *webview;}-(void)openDocumentIn;-(void)handleDocumentOpenURL:(NSURL *)url;-(void)displayAlert:(NSString *) str;-(void)loadFileFromDocumentsFolder:(NSString *) filename;-(void)listFilesFromDocumentsFolder;- (IBAction)btnDisplayFiles:(id)sender;@end


    检查绑定view和controller的准确性,选择file owner来查看:

    我们接着拖两个文件到resource下面;pdf文件和jpg文件,在

    OfflineReader-Info.plist 属性设置中, 设置 “Icon file” key 为 “icon.jpg”. 这样我们的程序有了图标,也有一个pdf作为本地resource目录下的文件

     如何导出文档:


    还是之前描述的,通过tap且hold可以激活其他app list,然后使用其他app来打开文件:以上是ios-iphone 邮件app的行为。如何在我们自己的app做到一样,可以把resource目录下的pdf传给其它app来打开呢?DIC是肯定要用到的:)

    #import "OfflineReaderViewController.h" @implementation OfflineReaderViewController UIDocumentInteractionController *documentController;
    先声明了一个dic变量,dic能够帮助提供in-app的支持,尤其在文件操作交互界面上。在这个例子中,我们用dic来export文档到另外一个app

     //Displays a menu for opening the document and anchors that menu to the specified view.

        [documentControllerpresentOpenInMenuFromRect:CGRectZero 

                                              inView:self.view 

                                            animated:YES];

    -(void)openDocumentIn {        NSString * filePath =         [[NSBundle mainBundle]         pathForResource:@"Courses for Q2 2011" ofType:@"pdf"];        documentController =         [UIDocumentInteractionController             interactionControllerWithURL:[NSURL fileURLWithPath:filePath]];    documentController.delegate = self;    [documentController retain];    documentController.UTI = @"com.adobe.pdf";    [documentController presentOpenInMenuFromRect:CGRectZero                                                    inView:self.view                                                  animated:YES];} -(void)documentInteractionController:(UIDocumentInteractionController *)controller          willBeginSendingToApplication:(NSString *)application { } -(void)documentInteractionController:(UIDocumentInteractionController *)controller              didEndSendingToApplication:(NSString *)application { } -(void)documentInteractionControllerDidDismissOpenInMenu:(UIDocumentInteractionController *)controller { }

    添加上面的函数,关键的opendocuemntin简单来说就是创建了指向特定pdf的路径,最后通过DCI呈现,程序中代码设定了UTI,这样系统才能帮助寻找对应的app(那些注册了能打开此类uti的app),这个和win8的file picker contract非常类似的概念。

    在代码中指定了com。adobe。pdf,代表了pdf文档。其它常用的有public。html/public。jpeg。。。那么其他几个方法主要是为了满足uidci protocol的要求。你可以考虑在其中作点工作,例如删除本地文件/log等

    - (void)viewDidLoad {    [super viewDidLoad];    [self openDocumentIn];}

    程序加载的效果如上/如果选ibook


    文档共享

    在iOS中,两个方法,要么通过itunes要么通过程序间的交换。。。

    我们先谈第一个方法,比较简单,通过plist修改下,声明可以通过itunes文档传输

    <key>UIFileSharingEnabled</key>

    <true/>

    属性 alias是application support itunes files sharing=YES

    这样,CMD+R编译,重新在真机上运行,打开ituens: 点击APPs,首先看到Sync APP:这里列出了支持sync的app,往下拖动,是File sharing//

    说明就是: 这里列出的app是支持设备和电脑之间通过itune文件传输的 


    注意:本例子所有测试在真机上进行,如果是模拟器,就没有ibook了。也没法测试和itunes链接的问题

    当文件拖动到app后,会存储在default document目录下
    -(void) displayAlert:(NSString *) str {    UIAlertView *alert =         [[UIAlertView alloc] initWithTitle:@"Alert"                                    message:str                                   delegate:self                         cancelButtonTitle:@"OK"                         otherButtonTitles:nil];    [alert show];    [alert release];    } - (void)handleDocumentOpenURL:(NSURL *)url {    NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];            [webView setUserInteractionEnabled:YES];        [webView loadRequest:requestObj];} -(void)loadFileFromDocumentsFolder:(NSString *) filename {    //---get the path of the Documents folder---       NSArray *paths = NSSearchPathForDirectoriesInDomains(          NSDocumentDirectory, NSUserDomainMask, YES);     NSString *documentsDirectory = [paths objectAtIndex:0];         NSString *filePath = [documentsDirectory         stringByAppendingPathComponent:filename];        NSURL *fileUrl = [NSURL fileURLWithPath:filePath];            [self handleDocumentOpenURL:fileUrl];} -(void)listFilesFromDocumentsFolder {        //---get the path of the Documents folder---        NSArray *paths = NSSearchPathForDirectoriesInDomains(         NSDocumentDirectory, NSUserDomainMask, YES);     NSString *documentsDirectory = [paths objectAtIndex:0];      NSFileManager *manager = [NSFileManager defaultManager];    NSArray *fileList =           [manager contentsOfDirectoryAtPath:documentsDirectory error:nil];    NSMutableString *filesStr =         [NSMutableString stringWithString:@"Files in Documents folder \n"];    for (NSString *s in fileList){            [filesStr appendFormat:@"%@ \n", s];    }    [self displayAlert:filesStr];        [self loadFileFromDocumentsFolder:@"0470918020.pdf"];} - (IBAction) btnDisplayFiles {    [self listFilesFromDocumentsFolder];    }
    第二中方法就是自己作为一个文档接受方:主要是通过注册,在plist中声明通过CFBundledocumenttypes


    Note the following:

    • The CFBundleDocumentTypes key is of type Array. It contains an array of dictionaries describing the types of documents supported by your application.
    • Item 0 is of type Dictionary.
    • The CFBundleTypeName key specifies the abstract name for the specified document type.
    • The LSHandlerRank key specifies whether the application is the owner (creator of this file type), Alternate (secondary viewer of this file type), None, or Default.
    • The CFBundleTypeRole key specifies the application’s role with respect to the type - Editor, Viewer, Shell, or None.
    • The LSItemContentTypes key is of type Array. It contains an array of UTIs specifying the file type.

    其实当文档触发app起来后,文档会被复制到一个inbox的目录,在documents目录下的一个子目录,可以通过url来看到路径

    #import "OfflineReaderAppDelegate.h"#import "OfflineReaderViewController.h" @implementation OfflineReaderAppDelegate @synthesize window;@synthesize viewController; -(BOOL)application:(UIApplication *)application            openURL:(NSURL *)url  sourceApplication:(NSString *)sourceApplication         annotation:(id)annotation {        if (url != nil && [url isFileURL]) {        [self.viewController handleDocumentOpenURL:url];    }        return YES;}

    关于自定义的应用:

    Importing Self-Defined Documents

    The previous section showed how to import well-known document types, such as PDF. What happens if you want to import your own self-defined document types? For example, you are writing a Sudoku game and wanted to implement your own file format for saving the state of a Sudoku game. In this case, your file might have the .sdk extension, which is only used by your application.

    To ensure that your application can handle files with the .sdk extension, you will add the keys as shown in Figure 16 to the OfflineReader-Info.plist file.


    Figure 16. Adding new keys to support self-defined document types

    Note that you added another key to the CFBundleDocumentTypes array. You set the LSItemContentTypes to a unique value, using the reverse domain name of your company and the type you are defining. Since this is a self-defined content type, you have to define it using the UTExportedTypeDeclarations key.

    Note: For more information on UTI, refer to Apple’s documentations – “Introduction to Uniform Type Identifiers Overview”.

    Press Command-R to test the application on a real device again. This time round, if your email contains a document of extension .sdk, you will see the icon of your application displayed next to the document name (see Figure 17). When you tap on the document name, you will see a list of options to open your documents with.