在IOS中实现导入&导出文档 (2012-04-21 21:19:52)
导入&导出文档时IOS开发者经常面临的开发需求。例如你开发一个文档阅读器允许用户导入他的文档到你的应用中以便离线阅读。又如,你的阅读器可以导出文档以便其他应用使用。
这篇文章,将介绍各种IOS开发中使用的文档导入&导出技术。
1.创建应用
像通常那样,我将用一个例子来说明。打开Xcode,创建一个View-based Application(iPhone)工程,并且命名为“OfflineReader”这篇文章,将介绍各种IOS开发中使用的文档导入&导出技术。
1.创建应用
双击OfflineReaderViewController.xib打开它,利用以下的views布局:
* UIWebView
* Round Rect Button
选择UIWebView,打开其属性标签页面,确保选上“Scales Page to Fit”项。
在OfflineReaderViewController.xib,添加以下代码:
#import
@interface OfflineReaderViewController : UIViewController
IBOutlet UIWebView *webView;
}
-(void)openDocumentIn;
-(void)handleDocumentOpenURL:(NSURL *)url;
-(void)displayAlert:(NSString *) str;
-(void)loadFileFromDocumentsFolder:(NSString *) filename;
-(void)listFilesFromDocumentsFolder;
-(IBAction) btnDisplayFiles;
@end
回到Interface Builder,连接IBOutlet和IBAction到UIWebView和UIButton。在File's Owner上右击后,会显示出现如下连接信息:
往工程里面拖进两个文件(如下图):一个PDF文件“Courses for Q2 2011.pdf”和一个icon.jpg图片文件。
打开OfflineReader-Info.plist文件,设“Icon file”键为“icon.jpg”
现在,你已经搭建了一个带图标的iPhone应用。而且,还有一个PDF文档在资源文件夹中。
2.导出文档
你首先学到的如何导入文档到你的应用当中。例如,在iPhone的邮件应用中,当你收到一个PDF文件,为了查看它,你可以点击上面的图标(如下图),或者点住不动。
如果你点住图标不动,会弹出一个action sheet(如下图)。你点击“Open in...”按钮就可以看到一个应用的列表,它表示你可以将文档导出的外部应用。
在我的iPhone上,它会显示如下:
那么,让我们现在修改我们的应用以便能导入在我们的资源文件夹中的PDF文档到外部应用。
首先,在OfflineReaderViewController.m中声明一个UIDocumentInteractionController类型的变量:
#import "OfflineReaderViewController.h"
@implementation OfflineReaderViewController
UIDocumentInteractionController *documentController;
UIDocumentInteractionController类提供了应用内用户文件交互的支持。在这个例子中,你会使用它来导出文档。
第二,实现以下方法:
-(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 {
}
openDocumentIn方法基本上用来创建一个指向PDF文档的路径(你将要导出的文档),通过它来关联documentController对象。你需要设置UTI(Uniform Type Identifiers,唯一类型标识)以便能让系统找到合适的应用来打开你的文档。在这个例子中,设置为“com.adobe.pdf”,表示PDF文档。其他的常用UTI有如“com.apple.quicktimemovie”(QuickTime movies),“public.html”(HTML文档),和“public.jpeg”(JPEG文件)。
可以查阅Apple官方文档得到已公开的UTI:System-Declared Uniform Type
其他三个方法定义在UIDocumentInteractionControllerDelegate protocol中。当documentController对象被调用是,它们会被回调。在该例中,你可以不实现这三个方法。
最后,在viewDidLoad方法中,添加如下代码:
- (void)viewDidLoad {
[super viewDidLoad]; [self openDocumentIn];
} 在真机上测试程序。当界面加载时,你会看见action sheet显示了一个应用列表(如下),你可以往列表中的应用导出你的文档。
如果你选择了iBooks,PDF文档显示如下:
2.文件分享
上一节展示了如何导出文档到外部应用。那么有什么方法可以导入文档。在IOS中,一般有两种方法:
* 通过iTunes
* 应用间的文件交换
现在讨论第一种方式。第一种方式用一种相当简单和直接的方式让用户传入或传出一些较大的文件到应用中。在OfflineReader-Info.plist中,添加键“UIFileSharingEnabled”如下:
现在运行程序。然后打开iTune
,选择你的设备(如下),再选择“Apps”标签,最后会看见你的OfflineReader应用显示着File Sharing:
为了向应用传入一个文件,只要把它拖进OfflineReader Documents的框框中(如下)。所以传入的文档都会放置在应用的Documents文件夹中。
如果要传出应用中的文件,你只要点击“Save to...”按钮即可。
现在,为了证明文件已经被传入到应用中,添加如下代码到OfflineReaderViewController.m中:
-(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];
}
运行应用,点击“Display files in Documents”按钮,WebView会显示出文件名和文件内容到(如下),证实了文件确实被成功传入了应用中。
3.文档导入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];
}
运行应用,点击“Display files in Documents”按钮,WebView会显示出文件名和文件内容到(如下),证实了文件确实被成功传入了应用中。
第二种传递文档的方法是通过其他应用(如第一节所说的)。在本文开头,你已经看到如何将PDF文档传到iBooks中并打开浏览。现在,你将学到如何将文档传入你的应用为你所用。
首先,你要使你的应用接受PDF文档。你需要做的是让IOS知道你的应用能接受PDF文档(注册应用)。打开OfflineReader-Info.plist,并如下修改,添加CFBundleDocumentTypes键:
解释如下:
* CFBundleDocumentTypes键:Array类型,它包含一个dictionary数组,这个dictionary表示你的应用可以支持的文档类型
* Item0类型为Dictionary
* CFBundleTypeName:文档类型名
* LSHandleRank:应用的所有者(以上声明的这种文件类型的创建者),有Alternate(这种文件类型的另外一个浏览者)、None或Default
* CFBundleTypeRole:应用通过什么方式处理这种文件:Editor、Viewer、Shell或None
* LSItemContentTpyes:Array类型,它包含表示这种文件类型的UTI数组
通过以上设置就可以向IOS注册你的应用,以便可以处理PDF文档。
当一个PDF文档传到应用中后,应用就会自动调用方法:application:openURL:sourceApplication:annotation: 该方法必须在application delegate中实现。
因此,添加如下代码:
#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;
}
当文档传入到应用中时,它会被复制到Document文件夹下的“Inbox”目录中。以上方法url参数表示Inbox目录的路径。一旦文档被传入,你将调用OfflineReaderViewController类的handleDocumentOpenURL:方法,以便加载文档到WebView。#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;
}
为了看看该文档的URL,添加如下代码(handleDocumentOpenURL:方法):
- (void)handleDocumentOpenURL:(NSURL *)url {
[self displayAlert:[url absoluteString]];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView setUserInteractionEnabled:YES];
[webView loadRequest:requestObj];
} 运行程序。这时,同样在email中浏览包含PDF的附件一样,点击图标不放,你将发现有个可以通过OfflineReader(你的应用)打开该文档的选项:
当文档通过你的应用中打开,你将看到如下:
4.导入自定义文档
上一节显示了如何导入司空见惯的文档,如PDF。如果到导入你自己定义的文档呢?例如一种从未见过的,只有你的应用可以打开的.sdk后缀的文档。
为了确保你的应用能处理.sdk文档,你要在OfflineReader-Info.plist中添加必要的键:
如上,在CFBundleDocumentTypes键的数组中添加多了一项。你设置了LSItemContentTypes一个唯一的值(自己定义)。因为这是你自定义的content-type,你必须用UTExportedTypeDeclaratios键来定义它(这种类型)。
备注:更多关于UTI的资料,请查阅Apple官方文档“Introduction to Uniform Identifiers Overview”
再次运行程序。这时,如果你的email包含了.sdk文件,你将看到IOS允许使用你的应用打开.sdk文件。