Is it possible to send a hash tag to a file url in UIWebView?
I want to load a html page from a file, and append a hash tag to it. Is this possible?
I have tried
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"someFile" ofType:@"html"];
NSURL *fileUrl = [NSURL fileURLWithPath:[filePath stringByAppendingFormat:@"#hashtag"]];
[self.webView loadRequest:[NSURLRequest requestWithURL:fileUrl]];
NSLog(@"fileUrl = %@, reachable? %d", fileUrl, [fileUrl checkResourceIsReachableAndReturnError:nil]);
but this tries to look for the file someFile.html%23hashtag
, which can't be found. Is there a way to add the hash after the NSURL
object is created?
I've also tried loading the file into a string and using loadHTMLString
:
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"someFile" ofType:@"html"];
NSString *fileContents = [NSString stringWithContentsOfFile:filePath en开发者_开发技巧coding:NSUTF8StringEncoding error:nil];
[self.webView loadHTMLString:fileContents baseURL:[NSURL URLWithString:@"http://someFile.html#hashtag"]];
Here the hash tag does work, but my javascript references inside the html don't work. A follow on question from this approach would be, how do I reference javascript files from html loaded in as a string in a UIWebView, ie, what is the base url?
A hack I can think of is to just put all my javascript files inline in the html and load it as a string, but I'm thinking there must be a better way!
I've not tried this but how about loading the file normally without the hashtag and implementing the UIWebViewDelegate with something like this?
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[webView stringByEvaluatingJavaScriptFromString:@"window.location.href = '#hashtag';"];
}
References:
- UIView that takes you to anchor link
- Programmatically scroll to an Anchor Tag
As to %23 issue, I don't think Scott Kohlert's replace solution is good.
The following solutions seems better, I just copied it from here
NSURL *baseUrl = [NSURL fileURLWithPath:stringUrl];
NSURL *fullURL = [NSURL URLWithString:@"#jumpto" relativeToURL:baseUrl];
A little bit off topic, I found the Safari on iOS 6.0, 6.1 behaves differenly than on iOS 5.1 and other desktop browsers(including Safari for OSX) regarding handle URL with anchor. For one of my particular document, whether in UIWebview or mobile Safari on iOS 6.0 or 6.1, upon the first load, the page isn't scrolled to the right position, a reload will fix it. Maybe it has something to do with the fact that part of the html is produced by javascript dynamically. Any ideas?
This is how I do it in my code. I append the hashmark to the NSString, then I turn it into an NSURL using fileURLWithPath. Then I replace all instances of %23 back into a #. Its all explained in the code below, but let me know if you have any questions.
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"someFile" ofType:@"html"];
NSString *filePathWithHash = [NSString stringWithFormat:@"%@#yourDesiredHashTagHere",filePath];
NSURL *theURL = [NSURL fileURLWithPath:filePathWithHash];
//NSURL turns the # into %23 when using fileURLWIthPath. So we need to change it back:
NSString *finalURLString = [[NSString stringWithFormat:@"%@",theURL] stringByReplacingOccurrencesOfString:@"%23" withString:@"#"];
//Then we need to change it back to an NSURL
NSURL *finalURL = [NSURL URLWithString:finalURLString];
//And finally we load this in the webView
[theWebView loadRequest:[NSURLRequest requestWithURL:finalURL]];
You should be able to intercept the NSURLRequest
, cast it to a NSMutableURLRequest
, then change the URL as follows. All this would happen in shouldStartLoadWithRequest
. Make sure you set the UIWebView delegate.
- (void) viewDidLoad
{
self.webView.delegate = self;
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"someFile" ofType:@"html"];
NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//Make sure the request is mutable
if(![request isKindOfClass:[NSMutableURLRequest class]])
[NSException raise:@"Need to change the request, but can't" format:@""];
NSMutableURLRequest* mutableRequest = (NSMutableURLRequest*)request;
NSString* newUrl = [NSString stringWithFormat:@"%@#hashtag", [[request URL] absoluteString]];
[mutableRequest setURL:[NSURL URLWithString:newUrl]];
return YES;
}
I haven't run into any cases where the request wasn't mutable, but who knows.
Or you may want to set the hash in the original URL (like you were doing), then replace the first occurrence of %23
with #
in shouldStartLoadWithRequest
.
An addition to @xiang's answer. Below the swift version if you're working with local html files in your app:
let urlString = "relative/path/to/your/index.html"
let anchorString = "#your-anchor"
let baseURL:NSURL? = NSBundle.mainBundle().URLForResource(urlString, withExtension: nil, subdirectory: nil)
if let url:NSURL? = NSURL(string: anchorString, relativeToURL: baseURL) {
// Do something with your URL
}
I think you have to add the hash after you create the file URL
Does it work if you change
NSURL *fileUrl = [NSURL fileURLWithPath:[filePath stringByAppendingFormat:@"#hashtag"]];
to something like:
NSString *urlString = [[NSURL fileURLWithPath:filePath] absoluteString];
NSURL *fileUrl = [NSURL URLWithString:[urlString stringByAppendingString:@"#hashtag"]];
In Swift (with WKWebView):
override func viewDidLoad() {
super.viewDidLoad()
webView.navigationDelegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let baseURL = Bundle.main.url(forResource: "myFile", withExtension: "html") {
//Load the main page and allow access to its directory
webView.loadFileURL(baseURL, allowingReadAccessTo: baseURL.deletingLastPathComponent())
}
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
let anchor = "#myanchor"
//Use javascript to jump to the location
webView.evaluateJavaScript("location.href = '" + anchor + "'", completionHandler: nil)
}
精彩评论