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?
Related
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
I have an iOS app which has XML file, that holds data for an app. That file contains links for web pages. For some reason, when I try to display this links with UIWebView, its not showing. There is white screen with black rectangle -
I know this problem is in my web links, but its perfectly correct when I try to open it in Mac or Windows browsers (in fact, I just copy-paste it from Wiki). For example, there is one of my links: http://ru.wikipedia.org/wiki/Московский_Кремль
And there is my code. It simple, but it do work when i test it with other link, like: http://apple.com
Code is below:
-(void)loadWebView{
NSURL *urlik = [NSURL URLWithString:self.entityLinkToWiki];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:urlik];
[self.myWebView loadRequest:requestObj];
}
// Note: self.entityLinkToWiki look like shown above - http://ru.wikipedia.org/wiki/Московский_Кремль
Of course I just don't want to force user to quit app and open link in Safari. Is there any way to show my stored web links in internal browser? And why is there such strange error? I mean links, that pretty fine in PC/Mac browsers doesn't work here?
UPDATED.
Guys, that was my fault and i terribly sorry for confusing you, and thank you for help. The problem is here: when i try to pass link string from one controller to another, somehow it lose part of text, and finally self.entityLinkToWiki = Московский_Кремль, not http://ru.wikipedia.org/wiki/Московский_Кремль as it should be!
My app have structure of table view, firstly, it load tableview, after that it pass values from XML which depends of indexPath.row. All values except web links works just fine, and i will explain the way i did this. As you request, there is part of web link in xml file:
<webpage>http://ru.wikipedia.org/wiki/Московский_Кремль</webpage>
To get that, i did following:
In "first" (tableView list) controller i pass values like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"detailSegue"]){
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSString *string = [[self.listOfPlaceDetails objectAtIndex:indexPath.row]objectForKey:#"description"];
DetailViewController *detailController = segue.destinationViewController;
detailController.descriptionStringShort =string;
....a lot of code here
detailController.fourthPhotoString = [[self.listOfPlaceDetails objectAtIndex:indexPath.row] objectForKey:#"imageFourth"];
detailController.webLink = [[self.listOfPlaceDetails objectAtIndex:indexPath.row]
objectForKey:#"webpage"];
}
}
Image link has nothing to do with web link, i just post it, so you get picture that i pass values in this way and it work fine. Then, i pass values from "detail" controller to controller, that finally have UIWebView:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
.... a lot of code here
if ([segue.identifier isEqualToString:#"WebSegue"]){
WebViewController *webController = segue.destinationViewController;
webController.entityLinkToWiki = self.webLink;
NSLog(#"WebSegue link is %#", self.webLink);
}
}
And NSLog says, that self.webLink is already - Московский_Кремль (incorrect value). Therefore, i didn't get correct link for my UIWebView. So now, my question is - how to get correct link passing it like i did? I don't want to bother load it from XML file in final controller, because i need information of indexPath.row, to get correct value (i have a lot of entities in XML file).
Thank you for any help you provide, and sorry about first post (in which i didn't bother to look at console and see, that my link was incorrect).
You have asked multiple questions. If you just want to open the Kremlin link in your browser - Use NSUTF8StringEncoding.
NSString doesn't have any function built in that really does URL encoding properly, but this one works for extended characters. This will definitely handle your foreign characters. I tested the following -
- (void) viewDidLoad{
[super viewDidLoad];
self.myWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
self.myWebView.delegate = self;
NSString *myString = #"http://ru.wikipedia.org/wiki/Московский_Кремль";
NSURL *urlik = [NSURL URLWithString:[myString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:urlik];
[self.myWebView loadRequest:requestObj];
[self.view addSubview:self.myWebView];
}
I am developing an app in Xcode but am having trouble with one part.
Basicly on the main app page, there is a small section that contains a web view. Everytime I change to another view controller and back, i see it flicker and reload. Is there a way to prevent it from reloading every time i open the view? instead just reloading every time I open the app.
This is the code:
NSURL *webUrl = [NSURL URLWithString:#"myurl.com"];
NSURLRequest *webrequestUrl = [NSURLRequest requestWithURL:webUrl];
[webView loadRequest:webrequestUrl];
webView.scrollView.scrollEnabled = NO;
webView.scrollView.bounces = NO;
Your webview is reloading every time you go to that screen is probably because you added it to either viewDidAppear: or viewWillAppear.
Add your block of code to the viewDidLoad method so it only gets executed when the view is loaded (aka when it's shown for the first time).
- (void)viewDidLoad:(BOOL)animated {
NSURL *webUrl = [NSURL URLWithString:#"myurl.com"];
NSURLRequest *webrequestUrl = [NSURLRequest requestWithURL:webUrl];
[webView loadRequest:webrequestUrl];
webView.scrollView.scrollEnabled = NO;
webView.scrollView.bounces = NO;
}
Edit: Oh by going to another view and back you meant going back on the navigation stack (or switching the navigation stack). In that case, you can keep a strong reference to your view controller with the webview and reuse it. Though I wouldn't suggest it doing it this was, unless that screen is the most important screen of your application.
Hope you are having your logic in other than the method
- (void)viewDidLoad
move your code to - viewDidLoad
even if your are having trouble then pass the preloaded UIWebView when ever you are navigating.
I have an app where on the very last UIViewController there is a UIWebView... the user navigates through the app and at the very end they can transition (modal) to the final UIViewController with a UIWebView... in it's viewDidLoad I have the UIWebView load the page.
The problem is it takes about 8 seconds to load this page and that annoys users.
How can I load the UIWebView way ahead of time (like when the app is first launched!) if that UIViewController hasn't even been presented yet?
I had your same problem for UIWebView inside a UIPageViewController and I found a better solution.
If you are in FirstViewController and you have your webView in your SecondViewController put the loadHTMLString or loadRequest method in the viewDidLoad of your SecondViewController and call [secondViewController.view layoutSubviews] for start loading in your FirstViewController.
Ex:
FirstViewController
-(void)viewDidLoad{
[super viewDidLoad];
// _secondViewController -> An instance of SecondVieController
[_secondViewController.view layoutSubviews];
}
SecondViewController
-(void)viewDidLoad{
[super viewDidLoad];
NSURL *url =[NSURL URLWithString:#"http://www.google.it"];
NSURLRequest *request =[NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}
What u can do is, load the html string
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:self.path ofType:#"htm"];
NSError * error;
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:&error];
and when u display the webView load this content in your webView
[self.webView loadHTMLString:htmlString baseURL:[[NSBundle mainBundle] bundleURL]];
then your webview need only render your content and doesn't load the data
/// In Swift 2.0
do{
let path = NSBundle.mainBundle().pathForResource("theName", ofType: "html")!
let html = try String(contentsOfFile: path, encoding: NSUTF8StringEncoding)
webView.loadHTMLString(html, baseURL: nil)
}catch{
print("Error is happend")
}
Note: It works the same way for WKWebView
Not sure how much work you want to do for this but I think you could cache/store the data from the URL in something like a NSDictionary, or something similar, using [NSUserDefaults standardUserDefaults] and use that information before actually loading the page.
So, load the first time you use it, after it has been seen then store the data using NSUserDefaults. Next time you go to this page, load from the NSUserDefaults first and call the URL/API in the back ground then update NSUserDefaults with this new data.
If you are requesting or pulling specific information each time, then I don't think this will work. If that is your case, you can probably try loading the data/website in an earlier view controller (probably one that takes the user a while to navigate to) and then send that data to the webview. Something like delegate/protocol or maybe even NSNotificationCenter. Hope this helps.
UIWebView is very tricky object. Simple answer would be: no you can't.
UIWebView won't load a document or an URL if it is not in views hierarchy.
Don't try doing it in different thread/queue either.
What you can do is to add UIWebView to the views hierarchy at the very beginning (as you've mentioned) and then pass it to the last view controller with preloaded data. This may work, but it's not an elegant way.
Side questions is: why does it take 8 secs to load a page? Maybe you can download the content of this page earlier? Is it static or dynamic?
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];