Add query string to local HTML files - ios

I have codes to load local html files (html files are inside the app, not from server), but how would I go about adding query string to it. I basically want to pass data from swift into html webview. Is this even possible? Alot of examples I've found is related to html files from server, but haven't found any for html files stored inside the app.
let url = NSBundle.mainBundle().URLForResource("index", withExtension:"html", subdirectory: "www")
let request = NSURLRequest(URL: url!)
webView.loadRequest(request)

To add query string parameters to local URL for WebView you can use code below. It is valid for Xcode 9 and Swift 4.
let bundleMainUrl = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "www");
let fullUrl = URL(string: "?os=ios", relativeTo: bundleMainUrl);
let request = URLRequest(url: fullUrl!);
webView?.load(request);

Yes you can do it by using Javascript. Check out stringByEvaluatingJavaScriptFromString
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWebView_Class/#//apple_ref/occ/instm/UIWebView/stringByEvaluatingJavaScriptFromString:

If you have a full URL string with the queries, you can just initialise NSURL with that string.
let url = NSURL(string: "www.stackoverflow.com")

You can use NSURLComponents and NSURLQueryItem to construct a URL with query parameters:
var urlComponents = NSURLComponents(string: "www/index.html")!
urlComponents.queryItems = [
NSURLQueryItem(name: "key1", value: "value1"),
NSURLQueryItem(name: "key2", value: "value2")
]
urlComponents.URL // returns www/index.html?key1=value1&key2=value2

I've solved this by using pathForResource instead of pathForResource as I was able to append string toward the end.
var url = NSBundle.mainBundle().pathForResource("index", ofType: "html", inDirectory: "www").stringByAppendingString("?os=ios")

Related

URL is nil or percentage encoded

I have this URL
https://apps.apple.com/developer/john-doe/id32123123#see-all/mac-apps
I do this
let path = "https://apps.apple.com/developer/john-doe/id32123123#see-all/mac-apps"
let url = URL(string: path!)
the resulting url is nil.
I do this:
var components = URLComponents()
components.scheme = "https"
components.host = "apps.apple.com"
components.path = "/developer/john-doe/id32123123#see-all/mac-apps"
let url = components.url!
The resulting url percentage encoded, like this and, as expect, an URLRequest done with that URL fails.
https://apps.apple.com/developer/john-doe/id32123123%23see-all/mac-apps
Is there a way to get a normal URL without any percentage encoding?
How do I do a URL that works with URLRequest?
This code works just fine:
let path = "https://apps.apple.com/developer/john-doe/id32123123#see-all/mac-apps"
let url = URL(string: path)
I just had to remove the !. Path is not optional, so there's nothing to unwrap.
Your latter technique isn't something you should bother using for literal URLs like this, but I can explain why it's "not working" to your expectations anyway. The # marks the beginning of the url's fragment. It's a special character, which is why the system is percent-encoding it for you when you try to use it as part of the path. Here's the fixed code:
var components = URLComponents()
components.scheme = "https"
components.host = "apps.apple.com"
components.path = "/developer/john-doe/id32123123"
components.fragment = "see-all/mac-apps"
let url = components.url! // => "https://apps.apple.com/developer/john-doe/id32123123#see-all/mac-apps"
You should read up on the URL standard.

Swift URL appendingPathComponent converts `?` to `%3F`

let url = URL(string: "https://example.com")
let path = "/somePath?"
let urlWithPath = url?.appendingPathComponent(path)
After appending, the path /somePath? becomes somePath%3F.
The ? becomes a %3F. Question Mark is replaced with the percent-encoded escape characters.
The URL does output correctly if I use:
let urlFormString = URL(string:"https://example.com/somePath?")
Why does appendingPathComponent convert ? to %3F?
How can I use appendingPathComponent if the path component contains a question mark?
The generic format of URL is the following:
scheme:[//[userinfo#]host[:port]]path[?query][#fragment]
The thing you have to realize is that the ? is not part of the path. It is a separator between path and query.
If you try to add ? to path, it must be URL-encoded because ? is not a valid character for a path component.
The best solution would be to drop ? from path. It has no meaning there. However, if you have a partial URL which you want to append to a base URL, then you should join them as strings:
let url = URL(string: "https://example.com")
let path = "/somePath?"
let urlWithPath = url.flatMap { URL(string: $0.absoluteString + path) }
In short, appendingPathComponent is not a function that should be used to append URL query.
You should use removingPercentEncoding on URL's absoluteString,
let url = URL(string: "https://example.com")
let path = "/somePath?"
let urlWithPath = url?.appendingPathComponent(path).absoluteString.removingPercentEncoding
print(urlWithPath!)
%3F stands for ?, according to URL Encoding. So if you create an URL - it has to be that way. If, for some reason, you need your ?, create a string, not URL.
Check urlWithPath.lastPathComponent to see that everything is all right (prints: "somePath?")
First of all it is not a problem. this is a mechanism called URL encoding, for translating unprintable or special characters to a universally accepted format by web servers and browsers.
For more information you can go to https://www.techopedia.com/definition/10346/url-encoding
URL encoded chars, https://www.degraeve.com/reference/urlencoding.php
When you convert the string to URL, It'll be doing PercentEncoding in URL. So that your ? has been encoded into %3F.
If you want the url as string with ?, you can remove the PercentEncoding as like below code.
let urlString = urlWithPath?.absoluteString.removingPercentEncoding
Output: https://example.com/somePath?
Instead of URL can use URLComponents:
var url = URLComponents()
Set the scheme, host and path:
url.scheme = "https"
url.host = "example.com"
url.path = "/somePath"
Set the query as empty string and ? is added since it is a separator between path and query:
url.query = ""
// url.queryItems = [URLQueryItem(name: "nameN", value: "valueX")]
Prints: https://example.com/somePath?
print(url)
You can build your url using NSString class:
let urlStr = "https://example.com" as NSString
let path = "/somePath?"
let urlStrWithPath = urlStr.appendingPathComponent(path)
let url = URL(string: urlStrWithPath)
This way, special characters are not url-encoded in the final url.

URL with added Anchor Tag Swift 4 Xcode 9

I try to add an anchor tag to local html file using this code:
let myAnchor ="#G"
let htmlPath = Bundle.main.path(forResource: "test", ofType: "html", inDirectory: "localWebsite", forLocalization:"")
let request = URLRequest(url: URL(fileURLWithPath: htmlPath! + myAnchor))
webview.load(request)
the answer is path/test.html%23G
so how I can convert to test.html#G ?
I don't know exactly what you want to achieve but you are speaking about encoding resp. decoding in your case. Your string is HTML encoded and you probably want to decode it. There are several answers for that already on this platform. One that would fit your needs is here: https://stackoverflow.com/a/39344394/1195661
You can construct an anchor tag relative to the filepath URL like this:
let baseURL = URL(fileURLWithPath: htmlPath)
if let url = URL(string: myAnchor, relativeTo: baseURL) {
print(url.absoluteURL)
// do your things
}

How to get a particular value from a Url in iOS - Swift 3

I have a url that is reg code attached to it. I just want to retrieve the reg code 7954741093-41547468-3 from the below url
https://mycode.funny.net/mycode/Registrations/7954741093-41547468-3?api-version=2011-04
You can use this:
let regCode:String = (url.components(separatedBy: "/").last?.components(separatedBy: "?").first)!
Where url is
let url:String = "https://mycode.funny.net/mycode/Registrations/7954741093-41547468-3?api-version=2011-04"
i think using URLComponents is a little more robust:
let url = "https://mycode.funny.net/mycode/Registrations/7954741093-41547468-3?api-version=2011-04"
let components = URLComponents(string: url)
components?.path.components(separatedBy: "/").last

Issue getting URL from String for use with AVPlayer

I have constructed a string that is the directory path and file name of file i would like to play in AVPlayer. But I'm struggling to convert this to a URL.
let dataPath = ("\(packDirectory)/").appending((cachedFilePath as NSString).lastPathComponent)
print(dataPath)
audioFileURL = dataPath
self.audioPlayerItem = AVPlayerItem(url: NSURL.fileURL(withPath: audioFileURL) as URL)
print(self.audioPlayerItem)
print(dataPath) returns:
/Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Application/788085B9-242E-46E7-9644-6A3BF9D515DB/Documents/Next-pk000/7b54d8a0f1a64b710058d4408ca4d696_The%20Name%20of%20the%20Wind%2029-92.mp3
print(self.audioPlayerItem) returns: - the url part:
URL = file:///Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Application/788085B9-242E-46E7-9644-6A3BF9D515DB/Documents/Next-pk000/7b54d8a0f1a64b710058d4408ca4d696_The%2520Name%2520of%2520the%2520Wind%252029-92.mp3
I don't really understand this stuff but i can see 2 issues with this.
1) file:// : i have purposely removed this from my "dataPath" as when using file manager it cant find anything with this prefix. i have used this code for that:
userDirectory.removeSubrange(userDirectory.startIndex..<userDirectory.index(userDirectory.startIndex, offsetBy: 7))
let packDirectory = userDirectory.appending("Next-\(self.selectedPack!)")
2) the encoding in the .lastComponent has been changed from %20 to %2520
Very confused !
---- EDIT ----
let urlItem = AVPlayerItem(url: URL(fileURLWithPath: audioFileURL))
if let urlAsset = urlItem.asset as? AVURLAsset {
self.audioPlayerItem = AVPlayerItem(url: NSURL(string: urlAsset.url.path) as! URL)
print(urlAsset.url.path)
}
print(self.audioPlayerItem!)
print(urlAsset.url.path) returns :
/Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Application/BAD0194A-8CDD-44CE-BF99-B9FF35E23BCA/Documents/Next-pk000/7b54d8a0f1a64b710058d4408ca4d696_The%20Name%20of%20the%20Wind%2029-92.mp3
print(self.audioPlayerItem!) returns:
<AVPlayerItem: 0x7bf81b60, asset = <AVURLAsset: 0x7bf87c70, URL = /Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Applicati ... 9-92.mp3>>
self.audioPlayerItem = AVPlayerItem(url: URL(fileURLWithPath: urlAsset.url.path))
prints:
file:///Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Application/7C212656-8E1C-44C8-9951-4444FB5EF853/Documents/Next-pk000/7b54d8a0f1a64b710058d4408ca4d696_The%2520Name%2520of%2520the%2520Wind%252029-92.mp3
even using something like:
let asset = AVAsset(url: URL(string: urlAsset.url.path)!) as AVAsset
results in losing some of the url:
<AVPlayerItem: 0x79716ed0, asset = <AVURLAsset: 0x797185d0, URL = /Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Applicati ... 9-92.mp3>>
And nothing plays. So basically i think it won't play with the file:// prefix but when i plug in the string without it something cuts the path at the i in applications???
You can read about absoluteString and path of URL documentation.
For getting self.audioPlayerItem's URL with lacking of file:/// you can access asset of self.audioPlayerItem and get path of asset.url
let asset = self.audioPlayerItem?.currentItem?.asset
if asset == nil {
return nil
}
if let urlAsset = asset as? AVURLAsset {
return urlAsset.url.path
}
Edited: if you use local file, init URL with URL.init(fileURLWithPath: ) instead of URL.init(string: ). If you use URL.init(string: ), string will be full path (contains file:///), not path.
That's ok, the decoding result is the same. Try to read reference A html space is showing as %2520 instead of %20
P/S: that snippet is just pseudo, please follow the idea from that snippet.

Resources