UIDocumentInteractionControllerの サポートされているファイルタイプ のいずれかからのクリックをインターセプトし、モーダルビュー(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ドキュメントには、ドキュメントコントローラを手動で保持する必要があるという事実が具体的に記載されているので、それを行いました。また、リリースする必要があるので、コントローラの場合はそうします。使用されなかった(topメソッド)と使用後にリリースしようとした(delegateメソッド)が、そのリリースがクラッシュを引き起こしていたので、削除したところ、その観点からは問題なく動作しているようです。
背景がわからないので、私の質問は、このコードがiPhoneシミュレーターで機能しているように見えるという事実と関係があります(オンラインドキュメントはpresentPreviewAnimated:
ビューに正しく表示されますが、 'OpenInはありません。 .. 'シムで使用できないダイアログ)、iPadシムまたは実際のiPhoneまたはiPadデバイスにpresentPreviewMethod:
が表示されていません。メソッドは正しく呼び出されていると思いますが、presentPreviewAnimated:
メソッドはNO
を返します。これは、ドキュメントのプレビューを表示できなかったことを意味します。
なぜこれでしょうか?ファイルを正しく保存していませんか(したがって、* pdfまたは* docなどとして検出されていません)?他に何が間違っている可能性がありますか? Appleドキュメント以外に、ドキュメントやサンプルコードはほとんどないので、100%動作させたいのですが、少なくともこのコードが誰かに役立つことを願っています。まず、よろしくお願いします。
[docController retain]
と[controller release]
という事実を無視して-[docController autorelease]
を試すことをお勧めします。戻った直後に何かをしようとしている可能性がありますが、実行中は後でありません。その場合は、コントローラーを解放する必要があります少し後でこれがautorelease
の目的です。それでもクラッシュする場合は、オブジェクトを所有していません。ただし、retain
する場合は、release
する責任があります。自動リリースしたら、nil
に設定して、もう一度触れないようにします。