【发布时间】:2011-03-20 12:01:09
【问题描述】:
我想拦截来自 UIDocumentInteractionController 的任何 supported file types 的点击,并将它们显示在模式视图中(由 UIDocumentInteractionController 的 presentPreviewAnimated: 方法提供)。此模式视图还提供“打开方式...”功能以在设备上的其他兼容应用程序中打开这些文档中的任何一个。下面的代码将拦截这些点击,检测 URL 字符串是否具有任何适当的后缀,加载此数据,将其写入目录,再次读取,最后通过 presentPreviewAnimated: 方法使用数据。我必须先将数据写入文件系统,因为 UIDocumentInteractionController 需要本地数据并且不能直接使用来自 URL 的数据(据我所知)。
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
ILog(@"URL loading for NavigationTypeLinkClicked: %@", request.URL.absoluteString);
if ([request.URL.absoluteString hasSuffix:@"pdf"] || [request.URL.absoluteString hasSuffix:@"doc"] || [request.URL.absoluteString hasSuffix:@"xls"] || [request.URL.absoluteString hasSuffix:@"ppt"] || [request.URL.absoluteString hasSuffix:@"rtf"] || [request.URL.absoluteString hasSuffix:@"key"] || [request.URL.absoluteString hasSuffix:@"numbers"] || [request.URL.absoluteString hasSuffix:@"pages"]) {
if (NSClassFromString(@"UIDocumentInteractionController")) {
NSArray *parts = [request.URL.absoluteString componentsSeparatedByString:@"/"];
self.previewDocumentFileName = [parts lastObject];
NSLog(@"The file name is %@", previewDocumentFileName);
// Get file online
NSData *fileOnline = [[NSData alloc] initWithContentsOfURL:request.URL];
// Write file to the Documents directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
if (!documentsDirectory) {NSLog(@"Documents directory not found!");}
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:previewDocumentFileName];
[fileOnline writeToFile:appFile atomically:YES];
NSLog(@"Resource file '%@' has been written to the Documents directory from online", previewDocumentFileName);
[fileOnline release];
// Get file again from Documents directory
NSURL *fileURL = [NSURL fileURLWithPath:appFile];
UIDocumentInteractionController* docController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
docController.delegate = self;
[docController retain];
BOOL result = [docController presentPreviewAnimated:YES];
if (!result) {
[docController release];
}
return NO;
}
}
}
// Do lots of other URL-detecting stuff here
}
我还实现了以下委托方法来使用适当的视图并在视图被关闭后删除文件(previewDocumentFileName 是一个类变量):
#pragma mark -
#pragma mark Document Interaction Controller Delegate Methods
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller {
return self;
}
- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:previewDocumentFileName];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:appFile error:NULL];
//[controller release]; // Release here was causing crashes
}
请注意,Apple 文档特别提到了需要手动保留文档控制器的事实,所以我这样做了。我也需要被释放,所以如果不使用控制器(顶级方法)并在使用后尝试释放它(委托方法),我会这样做,但该释放导致崩溃,所以我将其删除,事情似乎从这个角度来看工作正常。
在不影响背景的情况下,我的问题与以下事实有关:虽然此代码似乎在 iPhone 模拟器中工作(在线文档在 presentPreviewAnimated: 视图中正确显示,但没有“打开方式” ...' 不能在 sim 中使用的对话),它没有在 iPad sim 或我的实际 iPhone 或 iPad 设备上显示presentPreviewMethod:。我相信该方法被正确调用,但presentPreviewAnimated: 方法返回NO,这意味着它无法显示文档预览。
为什么会这样?我是否没有正确保存文件(因此它没有被检测为 *pdf 或 *doc 等)?我还能做错什么?除了 Apple 文档之外,几乎没有文档或示例代码,所以我希望至少这些代码对某人有所帮助,尽管我希望首先让它 100% 工作。提前致谢。
【问题讨论】:
-
[docController release]:开启clang。您应该会发现由于您不拥有控制器而生成了警告。 -
[controller release];- 这会导致崩溃,因为您不对这个对象负责。它在参数中为您提供。您尚未分配它以便能够释放它。 -
它对我来说很好用。谢谢瑞奇