This has got to be the dumbest question of the day, but I'm just not getting it.
I create a Quicklook, which shows just fine. When I hit the Done button, it just reappears. How do I intercept the Done button? Or more generally, control what is displayed in what I assume is a navbar. Here is the relevant code:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
/*
* get the path to the pdf resource.
*/
NSString *path = [[NSBundle mainBundle] pathForResource:#"article" ofType:#"pdf"];
NSURL *docURL = [NSURL fileURLWithPath:path];
/*
* create the Quicklook controller.
*/
QLPreviewController *qlController = [[QLPreviewController alloc] init];
PreviewItem *item = [[PreviewItem alloc] initPreviewURL:docURL WithTitle:#"Article"];
self.pdfDatasource = [[PDFDataSource alloc] initWithPreviewItem:item];
qlController.dataSource = self.pdfDatasource;
/*
* present the document.
*/
[self presentViewController:qlController animated:YES completion:nil];
}
I assume I am missing something obvious.
Thank you,
Ken
Did you tried Taking your ViewDidAppear code To ViewDidLoad ? As when you click on done button all the views of the Controller are being Loaded again except ViewDidLoad. So the quicklook view Appears again. Just Try
The trick was to roll everything back into the original viewcontroller. That way when I hit the done button it goes back to the original viewcontroller, which is exactly what I wanted. so instead of having a separate class, I just incorporated the calls right into my main viewcontroller. I suspect that there is still a way to do with a cunning use of delegates, but in case anyone else is having the same issue, this was a solution that worked for me.
Thank you for your attention and help.
Ken
Related
In iOS15, there is a new API to SFSafariViewController.Configuration that suggest one can add a custom button on the SafariViewController UI. This blogpost explains this in greater detail, under "Running custom extension".
I've been trying to implement this in a sample app without success. See the code snippet below:
- (void)openSfariViewController {
SFSafariViewControllerConfiguration *config = [[SFSafariViewControllerConfiguration alloc] init];
// Also tried the following extensionIdentifiers without success
// com.atomicbird.DemoNotes
// com.apple.share-services
SFSafariViewControllerActivityButton *button = [[SFSafariViewControllerActivityButton alloc] initWithTemplateImage:[UIImage systemImageNamed:#"heart.fill"] extensionIdentifier:#"com.atomicbird.DemoNotes.DemoNotes"];
config.activityButton = button;
SFSafariViewController *safariVC = [[SFSafariViewController alloc]initWithURL:[NSURL URLWithString:#"http://developer.apple.com"] configuration:config];
// safariVC.delegate = self;
[self presentViewController:safariVC animated:NO completion:nil];}
However I try to configure the new activityButton, it doesn't seem to have an effect on how SFSafariViewController appears when it is presented. It looks exactly like it does if I don't configure the activityButton. Here are some things I think I might got wrong:
I don't know what is the extensionIdentifier, perhaps I used a wrong value?
Perhaps I got the whole thing wrong, and an ActivityButton is not what I think it is?
Maybe the Share extension is not the configured properly?
I haven't been able to find any information on the web on how an activityButton is even supposed to look like. Thanks for reading this far, let me know if you have any pointers for me.
I'm using the UIDocumentInteractionController in iOS 7.1 and it's performing really badly.
I'm using it in a UICollectionViewController to view documents in a collection view.
On pressing an item in the collection view, it takes about around 6 (yes, that's six) seconds to appear. From a user experience perspective, they've pressed the screen a few more times before it appears because it takes so long.
I'm using the same code since iOS 6, but it seems particularly bad now. If anyone has any thoughts as to how I can speed things up, that would be greatly appreciated.
Essentially, I have the following in my header file:
interface MyViewController : UICollectionViewController <UIDocumentInteractionControllerDelegate>
{
UIDocumentInteractionController *docController;
}
#end
and in the implementation, I'm just doing the following:
In viewDidLoad (recently moved to here to see if it improves things):
docController = [[UIDocumentInteractionController alloc] init];
docController.delegate = self;
And then in the collectionView:didSelectItemAtIndexPath: I'm doing this:
NSURL *fileURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:document.Link ofType:#"" ]];
[docController setURL:fileURL];
PresentationViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"DocumentCell" forIndexPath:indexPath];
CGRect rect1 = cell.frame;
bool didShow = [docController presentOptionsMenuFromRect:rect1 inView:collectionView animated:YES];
where document is just a class with a string for the URL.
Let me know if you need any further detail.
Thanks in advance for any assistance anyone can provide.
-- Update:
After some NSLogs, I noticed that it's definitely the following line that's slow:
bool didShow = [docController presentOptionsMenuFromRect:rect1 inView:collectionView animated:YES];
TL;DR:
The method you are using is a synchronous request that uses your document data for find which apps are capable of reading your file. You need to swap with the asynchronous version that restricts the enumeration to only apps that can parse your file type.
Remove this method:
- (BOOL)presentOptionsMenuFromRect:(CGRect)rect
inView:(UIView *)view
animated:(BOOL)animated
And replace with this method:
- (BOOL)presentOpenInMenuFromRect:(CGRect)rect
inView:(UIView *)view
animated:(BOOL)animated
Excerpt from the Apple Docs:
This method is similar to the presentOptionsMenuFromRect:inView: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. To support one or more document types, an app must register those types in its Info.plist file using the CFBundleDocumentTypes key.
If there are no registered apps that support opening the document, the document interaction controller does not display a menu.
This method displays the options menu asynchronously. The document interaction controller dismisses the menu automatically when the user selects an appropriate option. You can also dismiss it programmatically using the dismissMenuAnimated: method.
I was encountering a similar problem with:
UIDocumentInteractionController.presentPreviewAnimated
It would take an incredibly long time to complete. I found adding a brief delay between saving the file to be previewed and presenting the preview fixed the problem:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(100 * NSEC_PER_MSEC)), dispatch_get_main_queue(), {
self.controller.presentPreviewAnimated(false)
})
Swift 4.2
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.controller.presentPreviewAnimated(false)
}
I have a UIViewController with a UIWebView where I'm placing a PDF.
The issue I'm facing is when I click on a table cell to show the PDF it does not show the first time however if i go back to the table and click on the cell again it appears.
I call the PDF to get loaded using the following:
if ([indexPath row] == 2)
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"myFirstPdf" ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webViewVC.webView loadRequest:request];
webViewVC.parent = _parent;
[_parent pushViewController:webViewVC];
}
The webViewVC itself I allocate using an initWithNib which has the UIWebView - nothing fancy there, simply a UIWebView with a IBOutlet.
Any ideas?
I think you should try 2 things:
(1) First, try loading the PDF from the web view controller. This is really the standard way to do this, rather than doing a load request for a web view that is not even on screen yet. All outlets are guaranteed to be loaded only in viewDidLoad of the controller.
(2) Second, try making use of the UIWebViewDelegate. For example, you could call setNeedsDisplay on the web view once loading is finished.
My idea : the first time you try the action your "webViewVC" hasn't been loaded yet, so webViewVC.webView is nil
the second time as you have displayed the webViewVC in your first attempt, it has been loaded, so webViewVC.webView isn't nil;
create a property on your webViewVC where you will set your request
and on your webViewVC viewWillAppear method do your [self.webView loadRequest:self.request];
So, I realize that there have been many questions regarding using a UIWebView to display a PDF in an app (on the iPad). I have reviewed everything I can find but I can't seem to find any satisfaction.
What I'm trying to do is very basic so I really don't know why it's not working. All I need to do is display a locally stored PDF in the UIWebView. Essentially, all I'm getting is a black screen. If someone could take a look at my code, I'd really appreciate it. Thanks.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Segue to the materials screen.
if ([segue.identifier isEqualToString:#"materials"]) {
PDFViewController *pdfViewController = [segue destinationViewController];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
int row = [path row];
Lesson *selected = [purchasedLessons objectAtIndex:row];
pdfViewController.selectedLesson = selected ;
//Start Load PDF in UIWebView
pdfViewController.pdfWindowTitle.title = selected.titleAndSubtitle;
pdfViewController.pdfWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 1024, 704)];
NSString *urlAddress = [[NSBundle mainBundle] pathForResource:#"moonlightSonataFirstMovement" ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[pdfViewController.pdfWebView loadRequest:requestObj];
//End Load PDF
}
}
I've checked to see if my object is bring passed into the scene properly (and it is) and if I am getting a proper request out; i'm getting:
<NSURLRequest file://localhost/Users/MYCOMPUTER/Library/Application%20Support/iPhone%20Simulator/5.0/Applications/AB161E57-D942-44C2-AA75-030087820BED/iLessons%20Piano.app/moonlightSonataFirstMovement.pdf>
Also, I've have this error message:
iLessons Piano[23080:f803] DiskImageCache: Could not resolve the absolute path of the old directory.
Additionally, the NSLog message gets printed out 8 times for some reason.
The only thing I can think of is that I need to do this loading when I call my prepareForSegue function in the previous scene. That or use a different method like Quartz. But I'd rather use a UIWebView since all I really need to do is display and allow scrolling.
DiskImageCache: Could not resolve the absolute path of the old
directory.
This one isn't the real reason the app crashes. This warning can be fixed by assigning the view in the Storyboard. It seems like it's connected already but it's grey. So assign it again and it will be fine.
The real issue for me was that the PDF images were 300 DPI and it took too long to load the application. Since the debugger keeps the app from crashing it seems to work fine but the loading will take too long without the debugger and will result in a timeout crash.
There's a few things you can do. You can downscale your PDF which might be a good thing anyway since older device are even slower and it's nice to support those as well. But what really fixes it is by delaying the PageView initialization. Here's what I did:
In the RootViewController I moved the code from the viewDidLoad to a new function setupPageViewer.
And put this in the viewDidLoad:
[self performSelector:#selector(setupPageViewer) withObject:nil afterDelay:0.0f];
The delay 0.0 means it will be taken care of in the next frame which gives you the opportunity to show a loading indicator.
Enjoy!
im not sure about whats going on .. you view and webView both holding nil value.. as i told you im not involved in the storyBoard yet .. but you as a workaround solution maybe this fix your problem
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1027, 768)];
pdfViewController.view = view;
pdfViewController.pdfWebView = [[UIWebView alloc] initWithFrame:pdfViewController.view.frame];
NSString *urlAddress = [[NSBundle mainBundle] pathForResource:#"moonlightSonataFirstMovement" ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:urlAddress];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[pdfViewController.view addSubview:pdfViewController.pdfWebView];
[pdfViewController.pdfWebView loadRequest:requestObj];
As a workaround, you can disable or remove your 'All Exceptions' breakpoint. This might make debugging a little more difficult, but it's not as bad as having to relaunch the application all the time.
This is the breakpoint causing the issue. I had set it so long ago that I'd forgotten it was there
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?