我需要让我的应用程序打开Safari和邮件应用程序中带有"在…中打开"的文档UIDocumentInteractionController
级的东西.我如何做到这一点?
我需要让我的应用程序打开Safari和邮件应用程序中带有"在…中打开"的文档UIDocumentInteractionController
级的东西.我如何做到这一点?
我知道,作为一名初级程序员,甚至作为一名中等技能的程序员,这让我非常沮丧.通过邮件和Safari应用程序进行文件I/O涉及非常...有趣的是,应用程序本身中的命名约定.让我们用iPhone的Xcode项目来解决问题.打开Xcode(本教程我将使用4.2), Select "单一视图"应用程序模板(或者创建一个空项目,然后添加一个带有.xib的单一视图).
在新创建的应用程序中,将视图控制器(以及相关的xib)重命名为OfflineReaderViewController
,然后我们将开始讨论代码.(除了前缀header和main.m之外,我们将处理所有文件,所以请注意,您需要面前的一切!)
输入AppDelegate标题并将以下代码粘贴到其中:
#import <UIKit/UIKit.h>
@class OfflineReaderViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) OfflineReaderViewController *viewController;
@end
然后输入代表的姓名.m文件并按原样粘贴以下代码:
#import "AppDelegate.h"
#import "OfflineReaderViewController.h"
@implementation AppDelegate
@synthesize window;
@synthesize viewController;
-(BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
// Make sure url indicates a file (as opposed to, e.g., http://)
if (url != nil && [url isFileURL]) {
// Tell our OfflineReaderViewController to process the URL
[self.viewController handleDocumentOpenURL:url];
}
// Indicate that we have successfully opened the URL
return YES;
}
- (void)dealloc
{
[window release];
[viewController release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[OfflineReaderViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
@end
这是:
-(BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
if (url != nil && [url isFileURL]) {
[self.viewController handleDocumentOpenURL:url];
}
return YES;
}
是本教程最重要的部分.将其分解为各个部分:-(BOOL)application:(UIApplication *)application
是我们的示例应用程序;openURL:(NSURL *)url
是用来告诉我们打开什么的URL;sourceApplication:(NSString *)sourceApplication
是发送链接的应用程序;annotation:(id)annotation
是一个额外的功能,我们不会进入.
现在,我们必须布局我们的xib.输入xib(应标题为"OfflineReaderServiceController",但这与xib无关,除非我们调用initWithNibName:
(我们不会这样做)),并使其看起来如下图所示:
这是非常重要的,你进入UIWebView
的属性,并判断"规模网页,以适应",因为这让我们放大和缩小网页与捏.暂时不要担心连接,我们很快就会创建这些连接.
输入OfflineReaderViewController
标题并粘贴到以下内容中:
#import <UIKit/UIKit.h>
@interface OfflineReaderViewController : UIViewController
<UIDocumentInteractionControllerDelegate> {
IBOutlet UIWebView *webView;
}
-(void)openDocumentIn;
-(void)handleDocumentOpenURL:(NSURL *)url;
-(void)displayAlert:(NSString *) str;
-(void)loadFileFromDocumentsFolder:(NSString *) filename;
-(void)listFilesFromDocumentsFolder;
- (IBAction) btnDisplayFiles;
@end
现在是.m:
#import "OfflineReaderViewController.h"
@implementation OfflineReaderViewController
UIDocumentInteractionController *documentController;
-(void)openDocumentIn {
NSString * filePath =
[[NSBundle mainBundle]
pathForResource:@"Minore" 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 {
}
-(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 {
[self displayAlert:[url absoluteString]];
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];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
[self openDocumentIn];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
@end
你们当中那些积极观看,而不仅仅是复制我告诉你们的一切(只是Jest )的人会知道,这一行:[[NSBundle mainBundle] pathForResource:@"Minore" ofType:@"pdf"];
将给我们一个SIGABRT,因为,嗯,文件不存在!所以,把你从任何地方提取的任何通用PDF都拖进go (我推荐here个,因为谁不花空闲时间阅读大量文档?),然后复制它的标题,并将后缀(.pdf)删除后粘贴进go ;ofType:@"pdf"
部分为我们解决了这个问题.完成后,线条应该是这样的:[[NSBundle mainBundle] pathForResource:@"//file name//" ofType:@"pdf"];
现在回到锡伯,把那IBOutlets
个都挂上!总而言之,以下是"文件所有者"选项卡的外观:
It seems we're done...but wait! We didn't do anything to get an "Open In..." menu up and running! Well, it turns out that there is some mucking around in the .plist file necessary. Open up the app .plist (with a quick right click, then select Open As > Source Code) and paste in the following:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFiles</key>
<array/>
<key>CFBundleIdentifier</key>
<string>CodaFi.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIFileSharingEnabled</key>
<true/>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>PDF Document</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.adobe.pdf</string>
</array>
</dict>
</array>
</dict>
</plist>
[旁注:在任何plist的源代码中都要小心,如果你不知道自己在做什么,你可能会从Xcode中得到可怕的"此文件已损坏"错误]
If one were to right click and select Open As > Property List, it would look like this:
还有一个非常重要的领域叫做"应用程序支持iTunes文件共享".必须设置为"是",否则你的应用程序将不会在iTunes中显示为支持文件共享.
"文档类型"字段指定我们的示例可以打开的文档类型.展开箭头以找到它的角色和UTI.这些是唯一标识符(唯一类型标识符;现在这个首字母缩写词的意思似乎很明显,不是吗?)每种文件都有.UTI让查找程序可以用文件类型的漂亮本地化图像替换通用文档图像(不要相信我,将一个不重要的文件扩展名重命名为.ouhbasdvluhb,并try 获得一张漂亮的图片!)如果我想打开自己的自定义格式(比如一个.code文件),那么我会在UTI字段中放入类似com.CodaFi.code
的内容(对于那些没有线索的人来说是反向DNS标记),文档类型名称将是"CodaFi Document".处理程序的级别和角色应该很简单,因为我们的处理程序级别是备用的(因为我们不拥有文件),而我们的角色是查看器(因为我们不需要任何更重要的东西).我们的示例只是一个查看器,而不是一个编辑器,所以我们将其保持原样.
为了将来的参考,UTI的官方系统公布了命名方案,当它们来自受人尊敬的来源(甲骨文、微软,甚至苹果本身)时,它们可以在Uniform Type Identifier Reference Guide中找到,但出于迂腐的考虑,被列为here.
现在,让我们跑吧!假设你一字不差地复制了那些该死的xib连接,代码应该不会出错.现在,当您第一次启动应用程序时,您应该可以 Select 在iBooks中打开文档.取消 Select 它,代码的真正内容是打开其他文档!启动Safari并搜索Safari可以快速查看或打开的任何PDF.然后在"开放中…"菜单,我们的应用程序出现了!点击它.你会看到小的switcheroo动画,一个提示会显示文件的位置.当你撤销它时,UIWebView
将加载PDF.邮件应用程序具有与附件类似的功能.你也可以将这些PDF文件调用到你的应用程序中.
就这样,一切都结束了.享受和快乐的编码!