How to detect "original" URL request in UIWebView - ios

I have a question that I couldn't find an answer to so far. Basically, I already know how to check the redirect URL:
func webView(webView: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
println(webView.request?.URL.absoluteURL)
if (navigationType == UIWebViewNavigationType.LinkClicked){
if (webView.request?.URL.path == "/contact-us") {
self.tabBarController?.selectedIndex = 4
}
return false
} else {
return true;
}
}
The problem I have now is that I implemented this code:
var path = NSBundle.mainBundle().bundlePath
var baseUrl = NSURL.fileURLWithPath("\(path)")
webView.loadHTMLString(finalHtml, baseURL: baseUrl)
Therefore, I am not getting the URL that is in the hyperlink. I believe this is because I changed the baseURL. Now, how should I get the "original" url in the tags?
Any suggestions would be greatly appreciated! =D
EDIT To make myself clearer, here is the output when I print out the request URL:
Optional(file:///Users/<My folder name>/Library/Developer/CoreSimulator/Devices/681E8ACA-B0EB-48B0-9FA4-FC89D3EE2044/data/Containers/Bundle/Application/8EB249C9-6362-4A92-B83F-8CDB5C181AAE/<appname>.app/)
Also, if the baseUrl was nil, I get "about:blank".

i'm not 100% sure of what youre asking but it seems like a simple string replacement.
NSString *path = webView.request?.URL.path;
NSString *cmp = [path stringByReplacingOccurrencesOfString:webView.request.baseURL
withString:#""];
if (cmp == "/contact-us") {
}
actually, just checking docs it seems you might just want the last path component
if (webView.request.URL.lastPathComponent == "contact-us") {
}

Related

How to get an auth code using ASWebAuthenticationSession?

I'm trying to obtain an auth code from Stripe's OAuth endpoint using ASWebAuthenticationSession - this event happens after the my Stripe redirect url gets called.
Unfortunately, the authSession's completion handler doesn't call back with a callbackURL. And I need this callbackURL to query the auth code. I've read different articles on this topic but I can't figure out why my implementation doesn't work they way I expect it to.
Here's my code:
class CreateStripeConnectAccountController: UIViewController {
var authSession: ASWebAuthenticationSession!
override func viewDidLoad() {
super.viewDidLoad()
configureAuthSession()
}
private func configureAuthSession() {
let urlString = Constants.URLs.stripeConnectOAuth // Sample URL
guard let url = URL(string: urlString) else { return }
let callbackScheme = "myapp:auth"
authSession = ASWebAuthenticationSession(url: url, callbackURLScheme: callbackScheme, completionHandler: { (callbackURL, error) in
guard error == nil, let successURL = callbackURL else {
print("Nothing")
return
}
let oauthToken = NSURLComponents(string: (successURL.absoluteString))?.queryItems?.filter({$0.name == "code"}).first
print(successURL.absoluteString)
})
authSession.presentationContextProvider = self
authSession.start()
}
}
extension CreateStripeConnectAccountController: ASWebAuthenticationPresentationContextProviding {
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
self.view.window ?? ASPresentationAnchor()
}
}
I believe the issue is that you are giving nil for callbackURLScheme. You need to give a URL scheme that redirects to your app:
See apple's authentication example: https://developer.apple.com/documentation/authenticationservices/authenticating_a_user_through_a_web_service
And here's apple's docs on how to create a custom URL scheme for your app: https://developer.apple.com/documentation/uikit/inter-process_communication/allowing_apps_and_websites_to_link_to_your_content/defining_a_custom_url_scheme_for_your_app.
I know it's old, but anyway.
Make sure, that callbackScheme and scheme that is used in redirect_uri are the same.
Your callbackScheme myapp:auth is incorrect format.
The symbol : cannot be used in the scheme name of a URI.
See the following RFC definition of Scheme.
Scheme names consist of a sequence of characters beginning with a
letter and followed by any combination of letters, digits, plus
("+"), period ("."), or hyphen ("-").
https://datatracker.ietf.org/doc/html/rfc3986#section-3.1
Thefore, revising the callbackURLscheme as myapp-auth or myapp.auth works well.
try setting your callbackScheme = "myapp" to receive callback
and from your server-side it should return "myapp://auth?token=1234"
Hope it helps.

Change URL last component name and add extension to the renamed one

I have the following URL
file:///Users/ivancantarino/Library/Developer/CoreSimulator/Devices/CCE2FCA5-05F0-4BB7-9A25-CBC168398A62/data/Containers/Data/Application/E48179F9-84FB-4CB3-B993-1E33FCFB5083/Library/Caches/CloudKit/34af81edf8344be1cf473ef394e06ccc8e1bc8cf/Assets/AE86E028-E4E0-45D5-B5FE-BAE975D07F2A.0166f7df06d2562d8d53e70a3779a46de3769584c3
I'm trying to rename the last part component of this url, but still having a url not only the filename.
I've managed to access the last part with the following code:
func extractAndBreakFilenameInComponents(fileURL: NSURL) {
let fileURLParts = fileURL.path!.components(separatedBy: "/")
let fileName = fileURLParts.last
print("filename:", fileName)
// prints: AE86E028-E4E0-45D5-B5FE-BAE975D07F2A.0166f7df06d2562d8d53e70a3779a46de3769584c3
}
I want to change the fileName to something like myFile.pdf but keeping the URL
It is a simple URL rename, not creating a new one, just changing the existing one
What's the best approach on this?
Thank you
You can also do with this way
var url = URL.init(string: "http://www.example.com/test123")
url?.deleteLastPathComponent()
url?.appendPathComponent("file.pdf")
print(url)
Output :http://www.example.com/file.pdf
Hope it helps to you
EDIT
You need to rename file use following code
1) Create Copy and update last component
var urlNew = URL.init(string: "http://www.example.com/test123")
urlNew?.deleteLastPathComponent()
urlNew?.appendPathComponent("file.pdf")
do {
try FileManager.default.moveItem(atPath: oldURL!, toPath: urlNew)
} catch {
}
You can do it this way
let fileName = fileURLParts.last
var newPath = ""
for i in 0 ..< fileURLParts.count
{
if i == (fileURLParts.count-1) {
newPath.append(fileName)
}else{
newPath.append(fileURLParts[i])
}
}

How can I open a URL without specifying HTTP or HTTPS in iOS?

In my iOS app I am opening links using the code below:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",myurl]]];
The links come dynamically and HTTP/HTTPS is not provided.
I cannot hardcode HTTP or HTTPS because I don't know if the URL has HTTP or HTTPS. How can I open a URL without specifying HTTP or HTTPS?
Solution for Swift:
let urlString = "example.com"
let urlHasHttpPrefix = urlString.hasPrefix("http://")
let urlHasHttpsPrefix = urlString.hasPrefix("https://")
let validUrlString = (urlHasHttpPrefix || urlHasHttpsPrefix) ? urlString : "http://\(urlString)"
I think this a better approach than the ones presented here, since it avoids string comparison & manipulation.
public extension URL {
var sanitise: URL {
if var components = URLComponents(url: self, resolvingAgainstBaseURL: false) {
if components.scheme == nil {
components.scheme = "http"
}
return components.url ?? self
}
return self
}
}
Who said you don't know whether url contain http or not? You can find out...
In prefixheader.pch write below.
#define contains(str1, str2) ([str1 rangeOfString: str2 ].location != NSNotFound)
Then in your .m write below.
if (!contains(myurl, "http")) {
myurl = [NSString stringWithFormat:#"http://%#", myurl];
}
You are done!!!
Let me know if you need anything else.
Matching with rangeOfString is not a good approach.
You can match it as:
NSString *urlScheme = [url scheme];
if (urlScheme == nil) {
url = [NSURL URLWithString:[NSString stringWithFormat:#"http://%#",urlString]];
}
And you don't have to worry about whether it's http or https. whenever you'll hit a url on http it'll automatically redirects to https

Retrieving and Parsing Text From Specific Webpage Using Swift

I need to retrieve the text from a specific website. However, I only need a few parts of it. How can I accomplish this using swift.
I have found the following in objective-c, but am not sure it provides how to reference it from a specific site:
NSString *webString = [webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.innerText"];
NSScanner *stringScanner = [NSScanner scannerWithString:webString];
NSString *content = [[NSString alloc] init];
while ([stringScanner isAtEnd] == NO) {
[stringScanner scanUpToString:#"Start of the text you want" intoString:null];
[stringScanner scanUpToString:#"End of the text you want" intoString:&content];
}`
I have put an example of what I mean below:
Again, I would like to accomplish this using Swift.
If your HTML was easily targetable with identifiers or class names, I would suggest using a library such as Kanna. But I've had a look at your page and the text you need is lost amidst an ocean of divs...
So I've quickly hacked a way to get your text with componentsSeparatedByString: I'm cutting the HTML in blocks until I get to the part we're interested in.
Note that it's far from being the most efficient way: instead of using componentsSeparatedByString you should come with a way of identifying the HTML block you want and search for it with NSScanner.
That being said, here's my example of a working hack, tested in a Playground:
enum CustomErrors : String, ErrorType {
case InvalidURL = "Invalid URL"
}
do {
let str = "http://www.golfwrx.com/328370/mizuno-to-offer-custom-grips-at-no-additional-charge/"
guard let url = NSURL(string: str) else { throw CustomErrors.InvalidURL }
let html = try String(contentsOfURL: url)
let separator1 = "<div class='mailmunch-forms-before-post' style='display: none !important;'></div><p>"
let temp = html.componentsSeparatedByString(separator1)
let separator2 = "</p>\n<p>"
let temp2 = temp[1].componentsSeparatedByString(separator2)
let separator3 = "</p><div class='mailmunch-forms-in-post-middle'"
let separated = temp2[1].componentsSeparatedByString(separator3)
let result = separated[0]
print(result)
} catch {
print(error)
}
Note: my example is in Swift 2 (Xcode 7).
Sorry about the specifics, I'm an Objective-C guy. but, here is an example of how to use NString to get the contents of a websites HTML
NSString *url = #"http://www.example.com"; // Your URL
NSURL *urlRequest = [NSURL URLWithString:url]; // Make a request with your URL
NSError *err = nil; // Error handler
NSString *html = [NSString stringWithContentsOfURL:urlRequest encoding:NSUTF8StringEncoding error:&err]; // Try to get the HTML in the string
if(err)
{
//Do something as it didn't work! Maybe a connection problem
}
else
{
// Use NScanner on html string
}
http://nshipster.com/nsscanner/ is a good place to learn about NScanner for swift
EDIT: Here is the above translated to swift
var err: NSError? // Error handler
let url: NSURL = NSURL(string: "http://www.example.com") // NSURL, put your website URL in here
let string = NSString(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &err) // String will now hold your HTML
// Now use NScanner (See Link) to parse the HTML output
My swift is rusty. but this might help you. This is roughly translated but outlines exactly what you need

How to get the html content from UIWebView?

I'm loading a web page using UIWebView
let urlStr = "http://duckduckgo.com"
let urlReq = NSMutableURLRequest(URL: NSURL(string: urlStr)!)
webView.loadRequest(urlReq)
Then, when the page has finished loading, I want to access the html content
func webViewDidFinishLoad(webView: UIWebView) {
let href = webView.stringByEvaluatingJavaScriptFromString("window.location.href")
println("window.location.href = \(href)")
let doc = webView.stringByEvaluatingJavaScriptFromString("document")
println("document = \(doc)")
}
But document just return an empty string (Optional("")). The window.location.href part is working fine. What I'm I doing wrong?
I think you have to evaluate the javascript like this:
let doc = webView.stringByEvaluatingJavaScriptFromString("document.documentElement.outerHTML")
In this case you get the entire HTML.
Now, when UIWebView is deprecated, you'll need to use syntax like this:
webView.evaluateJavaScript("document.documentElement.outerHTML") { (html, error) in
guard let html = html as? String else {
print(error)
return
}
// Here you have HTML of the whole page.
}
After that you can create a function like this that'll easily get HTML from webView:
func getHTML(_ completion: #escaping (String) -> ()) {
webView.evaluateJavaScript("document.documentElement.outerHTML") { (html, error) in
guard let html = html as? String else {
print(error)
return
}
completion(html)
}
}
getHTML { html in
// Here you have HTML string
print(html) // for example...
}
I Found the solution of problem regarding jqxWidget.
That UIWebView content were referencing .js and .css file which is already bundled in App. I had just only add the base url of App's MainBundle.
NSString *html = [self.webview1 stringByEvaluatingJavaScriptFromString: #"document.documentElement.outerHTML"]; //document.body.innerHTML
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
[objFullScreenViewCntrl.webview2 loadHTMLString:html baseURL:baseURL];

Resources