2010-07-24 23 views
30

Tôi muốn để đánh chặn các nhấp chuột từ bất kỳ supported file types của UIDocumentInteractionController và hiển thị chúng trong một cái nhìn phương thức (được cung cấp bởi presentPreviewAnimated: phương pháp UIDocumentInteractionController). Chế độ xem phương thức này cũng cung cấp chức năng "Mở trong ..." để mở bất kỳ tài liệu nào trong các tài liệu này trong các ứng dụng tương thích khác trên thiết bị. Mã bên dưới sẽ chặn các nhấp chuột này, phát hiện xem chuỗi URL có bất kỳ hậu tố thích hợp nào hay không, tải dữ liệu này, ghi dữ liệu vào thư mục, đọc lại và cuối cùng sử dụng dữ liệu với phương thức presentPreviewAnimated:. Trước tiên, tôi phải ghi dữ liệu vào hệ thống tệp vì UIDocumentInteractionController yêu cầu dữ liệu cục bộ và không thể sử dụng dữ liệu trực tiếp từ URL (theo như tôi đã đọc).Sử dụng UIDocumentInteractionController để hiển thị presentPreviewAnimated: qua 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 
} 

Tôi cũng thực hiện các phương pháp đại biểu sau đây để sử dụng giao diện phù hợp và để xóa các tập tin sau khi xem đã bị sa thải (previewDocumentFileName là một biến lớp):

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

Xin lưu ý rằng Apple Tài liệu đã đề cập cụ thể đến việc bộ điều khiển tài liệu cần được giữ lại theo cách thủ công, vì vậy tôi đã làm điều đó. Tôi cũng cần phải được phát hành, vì vậy tôi làm điều đó nếu bộ điều khiển không được sử dụng (phương pháp hàng đầu) và cố gắng phát hành nó sau khi nó được sử dụng (phương pháp đại biểu), nhưng bản phát hành đó đã gây ra sự cố, vì vậy tôi đã xóa nó và mọi thứ dường như để làm việc tốt từ quan điểm đó.

Với nền tảng trên đường đi, câu hỏi của tôi phải làm với thực tế là khi mã này có vẻ hoạt động trong trình mô phỏng iPhone (tài liệu trực tuyến được hiển thị chính xác trong chế độ xem presentPreviewAnimated:, mặc dù không có 'Mở trong. .. 'đối thoại không thể được sử dụng trong sim), nó không hiển thị presentPreviewMethod: trên sim iPad hoặc thiết bị iPhone hoặc iPad thực tế của tôi. Tôi tin rằng phương pháp này đang được gọi chính xác, nhưng phương pháp presentPreviewAnimated: đang quay trở lại NO, có nghĩa là nó không thể hiển thị bản xem trước tài liệu.

Tại sao điều này là? Tôi không lưu tập tin đúng cách (và do đó nó không được phát hiện như là một pdf * hoặc * doc, vv)? Tôi có thể làm gì khác sai? Có rất ít tài liệu hoặc mã ví dụ ngoài đó ngoài Tài liệu của Apple, vì vậy tôi hy vọng rằng ít nhất mã này sẽ hữu ích cho ai đó, mặc dù tôi muốn làm cho nó hoạt động 100% trước tiên. Cảm ơn trước.

+0

'[docController release]': bật clang. bạn sẽ thấy rằng một cảnh báo được tạo ra bởi vì bạn không sở hữu bộ điều khiển. – jww

+0

'[điều khiển phát hành];' - điều này gây ra sự cố vì bạn không chịu trách nhiệm về đối tượng này. Nó được cung cấp cho bạn trong tham số. Bạn đã không phân bổ nó để có thể phát hành nó. –

+0

Nó làm việc tốt cho tôi. Cảm ơn Ricky –

Trả lời

-1

trong phương pháp dealloc bạn chỉ cần viết

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

suy nghĩ nó sẽ làm việc cổ vũ!

1

Bỏ qua thực tế là bạn [docController retain][controller release] - Tôi khuyên bạn nên thử [docController autorelease]. Có một cơ hội nó đang cố gắng làm một cái gì đó ngay lập tức sau khi bạn quay trở lại, nhưng không phải sau này trong quá trình thực hiện. Nếu đúng như vậy, bạn muốn giải phóng bộ điều khiển một chút sau, đó là những gì autorelease dành cho. Nếu nó vẫn bị treo, bạn không sở hữu đối tượng. Mặc dù, nếu bạn đang nhập retain, bạn có trách nhiệm nhập release. Khi bạn đã tự động phát hành nó, hãy đặt nó thành nil để bạn không thử chạm lại vào lần nữa.

Các vấn đề liên quan