I have a test PDF file that I want to open in iBooks through my app. I saved it in my temp directory and I use this code to load it to iBooks:
NSURL *targetURL = [NSURL fileURLWithPath:tempFullPath];
NSLog(#"Path is %#", tempFullPath);
UIDocumentInteractionController *controller = [UIDocumentInteractionController interactionControllerWithURL:targetURL];
controller.delegate = self;
controller.UTI = #"com.adobe.pdf";
[controller presentOpenInMenuFromRect:self.view.bounds inView:self.view animated:YES];
The menu pops up just fine but when I tap the iBooks button the app crashes and hangs my Xcode.
The path to the file I get in my NSLog output is like this:
Path is /private/var/mobile/Applications/65EC4182-A79B-431C-9E74-BD72D91A31AB/tmp/TestFile.pdf
What am I doing wrong? Thanks in advance!
The use of a UIDocumentInteractionController requires that you keep a reference around until it is complete. This means you should use an instance variable, not a local variable. Implement the proper delegate methods so you can reset the ivar when you are done with the controller.
Enabling zombies will help debug such an issue. Most likely you will see that a message is being sent to a deallocated object (your controller).
Related
My application required to post an image to Instagram, I used UIDocumentInteractionController to open image file saved in the Documents directory with an extension .igo. Set com.instagram.exclusivegram as the UIDocumentInteractionController's UTI property. That all worked fine, my problem is that when I use
[dic presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
to open the UIDocumentInteractionController, it shows PDF reader, DropBox etc. I have to hide the other options than Instagram or show Instagram only. And also how to identify the Cancel button press in the presented menu.
Why is my UIDocumentInteractionController showing other options?
If you're using some code snippet from the Internet, make sure you implemented the delegate method correctly.
-(UIDocumentInteractionController *)setupControllerWithURL:(NSURL *)fileURL
usingDelegate:(id<UIDocumentInteractionControllerDelegate>) interactionDelegate
{
// if you're creating a new instance here,
// make sure you set the properties correctly
UIDocumentInteractionController *interactionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
// remember to set it again here
interactionController.UTI = #"com.instagram.exclusivegram";
interactionController.delegate = interactionDelegate;
return interactionController;
}
How can I know if a user cancel the action or proceed to Instagram?
Please refer to the answer of this thread: UIDocumentInteractionController Open Menu Cancelled Callback.
Heres the UIDocuemtnInteractionController from my application(does not show mail option)
Here the one that Apples sample project uses
Here are the respective codes
My application
docInteractionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
[docInteractionController presentOpenInMenuFromBarButtonItem:(UIBarButtonItem*)sender animated:YES];
Apple Sample Project
NSURL *fileURL;
if (cellIndexPath.section == 0)
{
// for section 0, we preview the docs built into our app
fileURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:documents[cellIndexPath.row] ofType:nil]];
}
else
{
// for secton 1, we preview the docs found in the Documents folder
fileURL = [self.documentURLs objectAtIndex:cellIndexPath.row];
}
self.docInteractionController.URL = fileURL;
[self.docInteractionController presentOptionsMenuFromRect:longPressGesture.view.frame
inView:longPressGesture.view
animated:YES];
WHAT SHOULD I DO TO GET THE MAIL OPTION?
To provide the Mail option, -presentOpenInMenuFromBarButtonItem: needs to be -presentOptionsMenuFromRect:
As per the Apple Docs on UIDocumentInteractionController
For -presentOpenInMenuFromBarButtonItem:animated: it says:
This method is similar to the
presentOptionsMenuFromBarButtonItem:animated: method, but presents a
menu restricted to a list of apps capable of opening the current
document. This determination is made based on the document type (as
indicated by the UTI property) and on the document types supported by
the installed apps.
...
If there are no registered apps that support opening the document, the
document interaction controller does not display a menu.
So:
To present options to open the file, use -presentOpenInMenuFromBarButtonItem:
To present all possible options applicable on the file, use -presentOptionsMenuFromBarButtonItem: or the generic -presentOptionsMenuFromRect:
Also... for any file, it would be better to specify the UTI type:
Example:
docInteractionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
//[docInteractionController setDelegate:self];
[docInteractionController setUTI:#"public.data"];
[docInteractionController presentOptionsMenuFromBarButtonItem:(UIBarButtonItem*)sender
animated:YES];
//or a generic method
//[docInteractionController presentOptionsMenuFromRect:sender.frame
// animated:YES];
I'm sharing a PDF to other apps through the UIDocumentInteractionController. Prior to adding this functionality, I had a custom 'send to email' button using the MFMailComposeViewController - yet now there's also a Mail button in my UIDocumentInteractionController, which I'd like to make use of, to avoid having duplicate buttons.
My issue is, through the old mail controller, I used to set a subject, and content text, whereas if I use the UIDocumentInteractionController - I only get a blank email with the PDF attachment. Does anyone know a way I could work round this and get my custom subject and content when using the UIDocumentInteractionController?
I couldn't find anything obvious in the documentation, and clearly I can't meddle with the Mail app to make it communicate with my app - but wondered if anyone else had encountered the problem, and sussed out a 'back-door' solution.
Below is the code for how I'm currently creating and initalising my UIDocumentInteractionController:
-(void)openDocumentIn:(NSString*)filepath
{
//NSString * filePath = [[NSBundle mainBundle]
pathForResource:filePath ofType:#"pdf"];
documentController = [UIDocumentInteractionController
interactionControllerWithURL:[NSURL fileURLWithPath:filepath]];
documentController.delegate = self;
documentController.UTI = #"com.adobe.pdf";
[documentController presentOptionsMenuFromBarButtonItem:
[self.imageViewController exportQuote] animated:YES];
}
You can do this through the following code
[self.documentInteractionController setName:#"My Email Subject"];
In the app that I am working I have files to be downloaded from a server and store it locally in the app's sandbox, then open it in iBooks using UIDocumentInteractionController.
I have done it all the downloading, saving, and opening it to iBooks. But, there are times that when I download a file then open it to iBooks it is not implementing, iBooks is not opening but the delgates are read from willBeginSendingToApplication: to didEndSendingToApplication: to documentInteractionControllerDidDismissOpenInMenu: (i put logs on it to check). Then if I restart the app it opens, then not open again, it is not consistent. What could be the problem?
Here my code for opening it to iBooks:
NSURL *url = [NSURL fileURLWithPath:filePath1];
DocController = [UIDocumentInteractionController interactionControllerWithURL:url];
DocController.delegate = self;
[DocController presentOpenInMenuFromRect:openIt.frame inView:menu animated:YES];
With UIDocumentInteractionControllerDelegate added in your .h, you can add this function :
- (UIViewController *) documentInteractionControllerViewControllerForPreview: (UIDocumentInteractionController *) controller
{
return self; //return the controller who open the doc
}
I am trying to use a singleton class to choose custom content to display based on the selection made by the user. It goes like this: a list is displayed, users select one of the rows in the list, and the app goes into another ViewController view. The ViewController used is the same for all the list options, however the content is different. Currently I managed to do this for only 1 option, and am trying to use a singleton class to tell the app which content to choose from.
This is what happens when the option "Raffles Landing Site" is chosen:
if(landmarkSelected== #"Raffles Landing Site") {
RafflesLandmarkInfo *rafflesLandmarkInfo = [[RafflesLandmarkInfo alloc] initWithNibName:#"RafflesLandmarkInfo" bundle:nil];
[self.navigationController pushViewController:rafflesLandmarkInfo animated:YES];
[rafflesLandmarkInfo release];
This opens a UIWebView implemented as follows:
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"raffles" ofType:#"html"]isDirectory:NO]]];
I created a singleton class as described here: http://www.galloway.me.uk/tutorials/singleton-classes/
I added an NSMutableString property to it and changed the previous codes to the following:
if(landmarkSelected== #"Raffles Landing Site") {
LandmarkController* instance = [LandmarkController sharedInstance];
[instance.activeLandmark setString:#"raffles"];
RafflesLandmarkInfo *rafflesLandmarkInfo = [[RafflesLandmarkInfo alloc] initWithNibName:#"RafflesLandmarkInfo" bundle:nil];
[self.navigationController pushViewController:rafflesLandmarkInfo animated:YES];
[rafflesLandmarkInfo release];
and
if (instance.activeLandmark ==#"raffles"){
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:instance.activeLandmark ofType:#"html"]isDirectory:NO]]];
}
but the app crashes when I select Raffles Landing Site from the list of options. The culprit seems to be
[instance.activeLandmark setString:#"raffles"];
How do I set the activeLandmark string in the first ViewController so when it loads the second ViewController it displays content based on the value set in the first ViewController?
In your singleton, is the activeLandmark string being alloced/initialized before you try and assign to it?