I'm pulling a URL from a string and turning that into a button to a WebView of the link.
This is the error I'm getting...
2015-11-10 18:58:05.159 MPSTApp[520:169178] -canOpenURL: failed for URL: "https:/www.facebook.com/prontosantateresa -- file:///" - error: "This app is not allowed to query for scheme file"
For this instance the string is https://www.facebook.com/prontosantateresa but I believe it's using the double // as an escape character.
The code calling the url link is such -
var anchorLink: String?
func loadWebPage(){
let requestURL = NSURL(string: anchorLink!)
let request = NSURLRequest(URL: requestURL!)
webView.loadRequest(request)
}
It's exactly what the error message says: It tries to open a file:// url. So, your algorithm for retrieving the https:// url seems to do something wrong and turn "//" into "/". It could also come handy to add the NSAllowArbitaryLoads key to your Info.plist.
I investigated issue. Since I was using an app browser, it didn't need to use UIApplication.canOpenUrl().
So, to resolve this I replaced the event method with below code in
#IBAction func website1ButtonPressed(sender: UIButton) {
if self.anchorLink != nil{
self.performSegueWithIdentifier("categoryDetailToWebSegue", sender: nil)
}
}
Related
I want to open some URLs with Safari browser of apple device. And my openURL function works fine most of the time. However when I tried to open this URL, it failed with the following error.
Download Failed Safari cannot download file.
Here is the URL that fails:
https://www.youtube.com/v/QH2-TGUlwu4?version=3&autohide=1
Here is my code:
let url = "https://www.youtube.com/v/QH2-TGUlwu4?version=3&autohide=1"
if let nsurl = NSURL(string: url){
if UIApplication.sharedApplication().canOpenURL(nsurl){
UIApplication.sharedApplication().openURL(nsurl)
}else{
print("Cannot open this NSURL.")
}
}else{
print("Cannot convert String to NSURL.")
}
The URL you mentioned
https://www.youtube.com/v/QH2-TGUlwu4?version=3&autohide=1
contains a SWF file i.e. Shockwave Flash file.
Flash cannot played on an iOS based device (link).
1) Either you need to show appropriate error message to user.
2) Or you can redirect user to YouTube app (instead of Safari), where user would be able stream and watch the video.
See this Apple doc link to understand how to redirect user to YouTube app.
You need to encode URL before use it like:
let urlString = "https://www.youtube.com/v/QH2-TGUlwu4?version=3&autohide=1"
var escapedString = urlString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
if let nsurl = NSURL(string: escapedString){
if UIApplication.sharedApplication().canOpenURL(nsurl){
UIApplication.sharedApplication().openURL(nsurl)
}else{
print("Cannot open this NSURL.")
}
}else{
print("Cannot convert String to NSURL.")
}
Here is my code,where the crash occurs:-
let URL = NSURL(string: "http://files.parsetfss.com/fa80bc63-88d4-412d-a478-2451cffc92a9/tfss-1d2a321d-b02e-4745-a589-e31536f648df-XXXXX%20CAT15%2030.p0001.jpg")
NSLog("Loading page with URL: \(URL)")
The app crashes with EXC_BAD_ACCESS
The first argument of NSLog() is a format string, and contains
format specifiers (starting with %) which are expanded by the
following variable argument list. In your case %20C is a format specifier, but
no matching argument is supplied. That causes undefined behavior,
it can crash or produce incomplete or wrong output.
If you want to use NSLog() then a general safe method is
NSLog("%#", "Loading page with URL: \(URL)")
In this particular case,
NSLog("Loading page with URL: %#", URL)
works as well, since NSURL is a NSObject subclass and can be used
with the %# format.
You should use println instead of NSLog.
let URL = NSURL(string: "http://files.parsetfss.com/fa80bc63-88d4-412d-a478-2451cffc92a9/tfss-1d2a321d-b02e-4745-a589-e31536f648df-XXXXX%20CAT15%2030.p0001.jpg")!
println("Loading page with URL: \(URL)")
I have added the option sign ! at the end to unwrap.
I use WKWebview to load a URL.
let webView = WKWebview()
let request: NSMutableURLRequest = NSMutableURLRequest(URL: url!)
webView.loadRequest(request)
How can I detect if the link the webView should load is broken?
You can use canOpenUrl method:
UIApplication.sharedApplication().canOpenURL(url)
It will do the url validation and if the link is ok it returns true.
It's mostly use before you call:
UIApplication.sharedApplication().openURL(url)
to make sure this link can be open in safari but it should help you here too.
Make sure the link starts with http:// or https://.
Edited:
It will just check is the link is a correct url.
If you want to see the page is offline, authorisation issues, etc. you can implement WKNavigationDelegate protocol and check out this method:
- webView:didFailNavigation:withError:
this should give you more info.
It's always good idea to use: str.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAl‌​lowedCharacterSet())!
it make sure that you don't pass a character which are not allowed in URL.
Edited 2:
To detect the status code you can try to implement:
- webView:decidePolicyForNavigationResponse:decisionHandler:
the navigation response is an NSURLResponse instance but
whenever you make an HTTP request, the NSURLResponse object you get back is actually an instance of the NSHTTPURLResponse class so you should cast it to NSHTTPURLResponse. That should give you a statusCode.
In the last line in the method you should call handler, for example decisionHandler(WKNavigationResponsePolicyAllow).
Ref: Answer exists here
if let url = NSURL(string: yourUrlString) {
var canOpen = UIApplication.sharedApplication().canOpenURL(url)
}
If you want to check if url string is correct and valid - just create NSURL object, if path contains error it will cast to nil:
let string = "http://google.com"
let url = NSURL(string: string)
let brokenString = "http:\\brokenurl.12"
let brokenUrl = NSURL(string: brokenString) // nil - it's not valid!
If you have implemented NSURLConnectionDelegate then below solution can be used.
didFailWithError method of NSURLConnectionDelegate can be used for this.
This method get called if an error occurs during the loading of a resource.
Can refer to below link
https://developer.apple.com/documentation/foundation/nsurlconnectiondelegate/1418443-connection
If my url has a space at the end it crashes with EXC_BAD_INSTRUCTION.
I thought canOpenURL would trap for a bad URL but it doesn't.
if let strurl = cell.url{
if (UIApplication.sharedApplication().canOpenURL(NSURL(string:strurl)!)) {
UIApplication.sharedApplication().openURL(NSURL(string:strurl)!);
}
}
In my case a URL with an extra space at the end crashes it. I can trim white space, but what about anything else? Is there a proper way to trap for this error?
You are force unwrapping NSURL which causes the app to crash if it happens to be nil. To check the validity of the URL you should be using if let on the URL itself as well.
if let strurl = cell.url,
let url = NSURL(string: strurl) {
if (UIApplication.sharedApplication().canOpenURL(url) {
UIApplication.sharedApplication().openURL(url)
}
}
Hi I am really new to coding in Swift, and am trying to follow the codes in this book: http://www.apress.com/9781484202098. Learn iOS 8 App Development 2nd Edition by James Bucanek
In particular, I am working through Chapter 3 - building a URL shortening app, but despite having copied the code exactly, I am getting an error on the code in Page 76:
if let toShorten = webView.request.URL.absoluteString {
which states 'NSURLRequest?' does not have a member named 'URL'.
I have tried googling an answer, but unfortunately have not come across anything. Any response I can find seems to suggest that my code ought to be working (e.g. How to get url which I hit on UIWebView?). This seems to have the closest answer SWIFT: Why I can't get the current URL loaded in UIWebView? but the solution does not appear to work for me. If I add a ? after the request, it will then at least build it, but I then have a nil variable returned.
I am using Xcode v6.1.1. Here is the piece of code that is coming up with the error in ViewController.swift:
let GoDaddyAccountKey = "0123456789abcdef0123456789abcdef" //this is replaced by my actual account key in my own code
var shortenURLConnection: NSURLConnection?
var shortURLData: NSMutableData?
#IBAction func shortenURL( AnyObject ) {
if let toShorten = webView.request?.URL.absoluteString { // ? now added
let encodedURL = toShorten.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
let urlString = "http://api.x.co/Squeeze.svc/text/\(GoDaddyAccountKey)?url=\(encodedURL)"
shortURLData = NSMutableData()
if let firstrequest = NSURL(string: urlString) //added if here and removed !
let request = NSURLRequest(URL:firstrequest)
shortenURLConnection = NSURLConnection(request:request, delegate:self)
shortenButton.enabled = false
}
}
}
If you have any suggestions on how I can fix this, I would really appreciate it!
Update:
Following suggestions from Ashley below, I have amended my code so that it is no longer bringing up the error (see comments above). However, it is now no longer running. This appears to be because the urlString is being created as http://api.x.co/Squeeze.svc/text/d558979bb9b84eddb76d8c8dd9740ce3?url=Optional("http://www.apple.com/"). The problem is therefore the Optional() that is included and thus makes it an invalid URL. Does anyone have a suggestion on how to remove this please?
request is an optional property on UIWebView:
var request: NSURLRequest? { get }
also stringByAddingPercentEscapesUsingEncoding returns an optional:
func stringByAddingPercentEscapesUsingEncoding(_ encoding: UInt) -> String?
What you need is to make user of optional binding in a few places:
if let toShorten = webView.request?.URL.absoluteString {
if let encodedURL = toShorten.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
let urlString = "http://api.x.co/Squeeze.svc/text/\(GoDaddyAccountKey)?url=\(encodedURL)"
shortURLData = NSMutableData()
if let firstrequest = NSURL(string: urlString) { // If a method can return a nil, don't force unwrap it
let request = NSURLRequest(URL:first request)
shortenURLConnection = NSURLConnection(request:request, delegate:self)
shortenButton.enabled = false
}
}
}
See Apple's docs on optional chaining for details
See Apple's docs for NSURL class