I'm using Objective-C. I want to open a local file with quick look. And I have this code in my mainViewController:
- (IBAction)open:(id)sender {
QLPreviewController *myQlPreViewController = [[QLPreviewController alloc]init];
myQlPreViewController.delegate = self;
myQlPreViewController.dataSource = self;
[myQlPreViewController setCurrentPreviewItemIndex:0];
[self presentViewController:myQlPreViewController animated:YES completion:nil];
}
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller
{
return 1;
}
- (id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
{
return [NSURL URLWithString:self.filePath];
}
But it shows a gray background and file name on it. How can I fix it to show the file content?
Thanks in advance!
In fact, it's because quick look can't open that file. So, it can only show a file name on the screen.
Related
I've been working with the Apple sample code for viewing documents from here:
https://developer.apple.com/library/ios/samplecode/DocInteraction/Listings/ReadMe_txt.html
I have removed all the bits I don't need and got it working pretty much how I would like it to. The problem is I don't want users to have access to the "Actions" menu on the top right of the Document Controller. This appears every time you select a document from the list:
Ideally I would like to remove the button all together, though if I could disable it or disable all the options inside it that would also suffice. I found this question:
Open in + UIDocumentInteractionController : how to filter options in SDK iOS 6 (canPerformActions is deprecated)
But I couldn't figure out how to use the suggestion to disable the options inside the menu. I have uploaded the modified sample code here:
http://plasma.servebeer.com/DocSampleCode.zip
One final note is this will not be going on the App Store it is for private, personal use, so if there is an unofficial way then I would be interested in knowing that too.
Any help would be greatly appreciated, thanks in advance.
Plasma
Use UINavigationControllerDelegate
#interface DITableViewController () <UIDocumentInteractionControllerDelegate, UINavigationControllerDelegate>
Assign navigationController delegate to self
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.delegate = self;
}
Change documentInteractionControllerViewControllerForPreview
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)interactionController {
return self.navigationController;
}
Add this UINavigationControllerDelegate method
// Called when the navigation controller shows a new top view controller via a push, pop or setting of the view controller stack.
- (void)navigationController:(UINavigationController*)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([viewController isKindOfClass:[QLPreviewController class]]) {
viewController.navigationItem.rightBarButtonItem = nil;
}
}
Update for MP4 files
In MP4 files the action button is on the UIToolbar
- (void)navigationController:(UINavigationController*)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([viewController isKindOfClass:[QLPreviewController class]]) {
viewController.navigationItem.rightBarButtonItem.customView = [[UIView alloc] init];
UIBarButtonItem *item = viewController.toolbarItems.firstObject;
item.customView = [[UIView alloc] init];
}
}
N.B. This might not work in future versions of iOS
After creating QLPreviewController class you would need to set rightBarButtonItem to nil. Code snippet:
QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.navigationItem.rightBarButtonItem = nil;
I did download project and after execution "Action" button was shown not in the top navigation item, but in the toolbar. Then in this case you would need to subclass QLPreviewController and override viewWillAppear as shown below.
#implementation ExViewController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSMutableArray *a = [NSMutableArray arrayWithArray:#[]];
for (NSUInteger i = 0; i < self.toolbarItems.count; i++) {
if (i == 0) {
continue;
}
[a addObject:self.toolbarItems[i]];
}
}
#end
If you want to hide button the give answers will not work for iOS 10.0 and above in Swift language. You can use WKWebView. Hope it will save your time.
I am using this great STPopup:
http://cocoadocs.org/docsets/STPopup/1.2.0/Classes/STPopupController.html
- (void)showPopupWithTransitionStyle:(STPopupTransitionStyle)transitionStyle rootViewController:(UIViewController *)rootViewController
{
STPopupController *popupController = [[STPopupController alloc] initWithRootViewController:rootViewController];
popupController.cornerRadius = 4;
popupController.transitionStyle = transitionStyle;
[popupController presentInViewController:self];
//[popupController dismissWithCompletion:^{NSLog(#"Dismissed!");}];
}
- (IBAction)btnClick:(id)sender {
[self showPopupWithTransitionStyle:STPopupTransitionStyleSlideVertical rootViewController:[ad new]];
}
This is working fine so far, but i want to execute a code when popup is closed. How can i do this?
Thx!
In my opinion the best solution.
- (void)didMoveToParentViewController:(UIViewController *)parent
{
if (![parent isEqual:self.parentViewController]) {
NSLog(#"Popup close!");
}
}
But it only works with iOS5+
Instead of
[popupController presentInViewController:self];
use following code,
[popupController presentInViewController:self completion:^{
NSLog(#"Dismissed!");
//execute your code when popup is closed, here!
}];
EDIT:
you can use following method for executing code after dismissing the popup.
- (void)dismissWithCompletion:(void ( ^ ) ( void ))completion
The viewWillDisappear&viewDidDisappear of the view controller, which is shown in popup controller, will be called when the popup controller is dismissed.
I have this code which previews the PDF file:
QLPreviewController *previewController=[[QLPreviewController alloc]init];
previewController.delegate=self;
previewController.dataSource=self;
[self presentModalViewController:previewController animated:YES];
Now, when I close QLPreviewController or previewController this method is called:
- (void)previewControllerDidDismiss:(QLPreviewController *)controller {
NSLog(#"You closed the document");
}
Now, how I can return the document's or Pdf's URL when I call this method:
- (void)previewControllerDidDismiss:(QLPreviewController *)controller {
//here I need to be able to get the PDF's URL or Data when is closed
}
Can anyone please help?
Many thanks.
Check documentation here. There is another method, that responds to user actions and returns needed URL:
- (BOOL)previewController:(QLPreviewController *)controller
shouldOpenURL:(NSURL *)url
forPreviewItem:(id<QLPreviewItem>)item
I have a PDF file saved in the document directory. The path to the file is stored in a NSString property 'self.URL'.
Here is my code to present the activity items:
-(void)presentDocumentInteractionController{
self.docController = [UIDocumentInteractionController interactionControllerWithURL:self.URL];
self.docController.delegate = self;
[_docController setUTI:#"com.adobe.pdf"];
[_docController presentOptionsMenuFromBarButtonItem:self.activityBarButton animated:YES];
}
Before iOS 8 this code worked fine. The user was presented with a list of items such as print, copy and email to choose from. After upgrading to iOS 8 /XCode 6, I'm getting this runtime error (it doesnt crash the app):
Unknown activity items supplied: (
"<UITextViewPrintFormatter: 0x7f908ba53ca0>"
)
How can I solve this problem?
I have the same problem and have switched to using UIActivityViewController. However this makes the apps capable of opening the PDF no longer show up, so maybe that's not what you want.
Minimal Solution:
If you want to do minimal work, you don't even need to read your PDF into NSData, use a NSURL as activity item and iOS seems to know what to do:
- (void)share:(id)sender
{
UIActivityViewController *activity =
[[UIActivityViewController alloc] initWithActivityItems:#[self.URL]
applicationActivities:nil];
if ([activity respondsToSelector:#selector(popoverPresentationController)]) {
activity.popoverPresentationController.barButtonItem = <# BAR BUTTON ITEM #>;
}
[self presentViewController:activity animated:YES completion:NULL];
}
Original Answer:
Make your view controller adhere to the UIActivityItemSource protocol, then you can do:
- (void)share:(id)sender
{
self.pdfData = [NSData dataWithContentsOfURL:self.URL];
UIActivityViewController *activity = [[UIActivityViewController alloc] initWithActivityItems:#[self] applicationActivities:nil];
if ([activity respondsToSelector:#selector(popoverPresentationController)]) {
activity.popoverPresentationController.barButtonItem = <# BAR BUTTON ITEM #>;
}
[self presentViewController:activity animated:YES completion:NULL];
}
Adhering to the protocol if you have a PDF file is relatively simple. You can of course optimize and return smaller NSData and even a preview image, but minimally do this:
- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{
return _pdfData;
}
- (id)activityViewController:(UIActivityViewController *)activityViewController
itemForActivityType:(NSString *)activityType
{
return _pdfData;
}
- (NSString *)activityViewController:(UIActivityViewController *)activityViewController
subjectForActivityType:(NSString *)activityType
{
return self.title;
}
- (NSString *)activityViewController:(UIActivityViewController *)activityViewController
dataTypeIdentifierForActivityType:(NSString *)activityType
{
return #"com.adobe.pdf";
}
Use
- (BOOL)presentOpenInMenuFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;
Instead of
- (BOOL)presentOptionsMenuFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;
This solved the problem for me:
ObjC:
dispatch_async(dispatch_get_main_queue(), ^() {
[_docController presentOptionsMenuFromRect:button.bounds inView:button animated:YES];
});
Swift:
if let docController = UIDocumentInteractionController(URL: url) {
dispatch_async(dispatch_get_main_queue()) {
docController.presentPreviewAnimated(true)
}
} else {
// handle nil docController
}
I don't use swift so this code might not work.
I know QLPreviewController could do this. But it's full screen, my requirement is preview files in a subview.
I tried use a offline window to present the QLPreviewController, and then make a screenshot of the offline window.
The problem is i have to show the window, otherwise the screen shot doesn't catch any thing.
Then my question could be, how to make screen shot for offline window in ios ?
Or you may have better ideas of implement file preview in another way.
Any tips will be appreciated.
QLPreviewController can be in a subview.
I self use it in a spliview and a subclassed QLPreviewController.
- (void)tableView:(UITableView *)tView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DocumentViewController *documentViewController = [DocumentViewController new];
[self.navigationController pushViewController:documentViewController animated:YES];
[documentViewController release];
}
where DocumentViewController is a subclass of QLPreviewController:
#interface DocumentViewController : QLPreviewController <QLPreviewControllerDataSource>
#implementation DocumentViewController
...
- (id)init
{
self = [super init];
if (self)
{
self.dataSource = self;
self.delegate = self;
}
return self;
}
...
and implement the methods witch you want (numberOfPreviewItemsInPreviewController is required for the datasource)