2010-07-24 66 views
30

我想從任何UIDocumentInteractionController的supported file types的攔截點擊和在一個模態的視圖(由UIDocumentInteractionController的presentPreviewAnimated:方法提供)顯示它們。此模式視圖還提供了「打開在...」功能,可在設備上的其他兼容應用程序中打開這些文檔中的任何一個。下面的代碼將攔截這些點擊,檢測URL字符串是否具有任何適當的後綴,加載此數據,將其寫入目錄,再次讀取並最終使用presentPreviewAnimated:方法中的數據。我必須首先將數據寫入文件系統,因爲UIDocumentInteractionController需要本地數據,並且不能直接從URL使用數據(據我所知)。使用UIDocumentInteractionController顯示presentPreviewAnimated:經由的UIWebView

- (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 
} 

請注意,蘋果文檔中特別提到了文檔控制器需要手動保留的事實,所以我這樣做了。我也需要被釋放,所以如果控制器沒有被使用(頂端方法)並試圖在它被使用之後釋放它(委託方法),但是那個版本導致崩潰,所以我刪除它並且看起來似乎從這個角度來說工作得很好。

以背景爲例,我的問題與這樣一個事實有關,儘管此代碼似乎在iPhone模擬器中工作(聯機文檔在presentPreviewAnimated:視圖中正確顯示,儘管沒有「打開」 ..'對話,不能在SIM卡中使用),它不會在iPad上顯示presentPreviewMethod:或我的真實iPhone或iPad設備。我相信該方法被正確調用,但presentPreviewAnimated:方法正在返回NO,這意味着它無法顯示文檔預覽。

這是爲什麼?我是不是正確保存文件(因此它不會被檢測爲* pdf或* doc等)?我還能做什麼錯?除了Apple文檔之外,還有很少的文檔或示例代碼,所以我希望至少這個代碼對某個人有幫助,儘管我希望首先讓它工作100%。提前致謝。

+0

''[docController release]':打開鐺。您應該發現由於您不擁有控制器而產生警告。 – jww 2011-04-01 10:44:48

+0

'[controller release];' - 這會導致崩潰,因爲您不對此對象負責。它在參數中爲您提供。您尚未分配它才能釋放它。 – 2011-11-17 21:40:56

+0

它對我來說工作正常。 謝謝瑞奇 – 2013-11-19 10:52:28

回答

-1

在dealloc方法,你只要寫

- (void)dealloc { 
[controller release]; 
controller = nil; 
[super dealloc]; 
} 

認爲這會工作 歡呼!

1

忽略你的事實[docController retain][controller release] - 我建議你試試[docController autorelease]。你有機會在你返回後立即嘗試做某些事情,但不會在執行期間稍後再做。如果是這種情況,您想稍後釋放控制器,這是autorelease的用途。如果它仍然崩潰,你不擁有這個對象。但是,如果您是retain,那麼您需要對release負責。一旦你已經autoreleased它,將其設置爲nil,所以你不要再嘗試觸摸它。