19

I am trying to open a website in my app, but for some reason one line keeps returning nil, heres my code:

let url = URL(string: "http://en.wikipedia.org/wiki/\(element.Name)")!
    if #available(iOS 10.0, *) {
        UIApplication.shared.open(url, options: [:], completionHandler: nil)
    } else {
        UIApplication.shared.openURL(url)
    }
}

It's the first line (let url = URL...) that keeps on returning this error:

fatal error: unexpectedly found nil while unwrapping an Optional value.

What should I do to fix this?

Benja0906
  • 1,437
  • 2
  • 15
  • 25
  • 1
    Check `element.Name`. If it's an optional String Interpolation can cause unexpected behavior. – vadian Nov 01 '16 at 20:58

9 Answers9

26

I think this will help. Your element.name may contain space between words so addingPercentEncoding make PercentEncoding string.

let txtAppend = (element.Name).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let url = "http://en.wikipedia.org/wiki/\(txtAppend!)"
let openUrl = NSURL(string: url)
if #available(iOS 10.0, *) {
    UIApplication.shared.open(openUrl as! URL, options: [:], completionHandler: nil)
} else {
    UIApplication.shared.openURL(openUrl as! URL)
}
Dipal Patel
  • 327
  • 3
  • 8
15

Swift 4 version for this fix:

str.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
BlaShadow
  • 11,075
  • 7
  • 39
  • 60
11

This will definitely works for you. The problem is occurring due to space in between your string URL. To fix this use

let imagePath = "https://homepages.cae.wisc.edu/~ece533/images/arcti cha re.png"

let urlString = imagePath.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) //This will fill the spaces with the %20

let url = URL(string: urlString) //This will never return nil
Navdeep Paliwal
  • 349
  • 3
  • 7
7

Don't force unwrap it with (!). When you use (!) and the value of the variable is nil, your program crashes and you get that error. Instead, you want to safely unwrap the optional with either a "guard let" or an "if let" statement.

guard let name = element.Name as? String else {
    print("something went wrong, element.Name can not be cast to String")
    return
}

if let url = URL(string: "http://en.wikipedia.org/wiki/\(name)") {
    UIApplication.shared.openURL(url)
} else {
    print("could not open url, it was nil")
}

If that doesn't do the trick, you may have an issue with element.Name. So I would check to see if that's an optional next if you're still having issues.

Update

I added a possible way to check the element.Name property to see if you can cast it as a String and create the desired url you're looking to create. You can see the code above the code I previously posted.

user3353890
  • 1,844
  • 1
  • 16
  • 31
  • 1
    This only solves the error, not the cause of the error. I'm sure the goal is to end up with a valid URL. – rmaddy Nov 01 '16 at 21:58
  • can you please explain further? If he/she is not getting a valid url from this, then I would look next at the element.Name property. – user3353890 Nov 01 '16 at 22:23
  • The OP want to create a URL using `element.Name`. As is, that is causing the URL to be `nil` resulting in a crash. Your answer simply prevents the crash but it doesn't solve the issue of creating the URL as desired. – rmaddy Nov 01 '16 at 22:26
  • It solves the error that was given in the question. I agree with you that it doesn't give a full solution for creating a url from element.Name, but I don't know what more I can do without knowing more information about element.Name. – user3353890 Nov 01 '16 at 22:37
  • @rmaddy I added an additional check on element.Name to give a complete solution. Hopefully, this will be satisfactory. If not, I would love your guidance on how it can be improved. – user3353890 Nov 01 '16 at 22:49
  • The likely issue is that `element.Name` contains characters that need to be escaped such as spaces or other special characters. – rmaddy Nov 01 '16 at 22:50
  • ahh, ok. That makes sense. Thanks for the explanation! – user3353890 Nov 02 '16 at 06:56
  • Thank you, it works now! No errors and it loads the website perfectly – Benja0906 Nov 02 '16 at 14:16
3

I'm going to guess that your URL is not properly formated after adding the element.Name . so just use the function

addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)

It's just surprising that the URL constructor doesn't take the URL format into consideration

JPilson
  • 1,075
  • 11
  • 10
  • This is wrong. The idea is good but this is not how you correctly encoded URL query. This won't correctly encode chars like `?`, `&` or `+`. – Sulthan Oct 24 '22 at 13:04
1

it may be an encoding issue. have you tried

let str = "http://en.wikipedia.org/wiki/\(element.Name)"
let encodedStr = str.stringByAddingPercentEncodingWithAllowedCharacters(NSCha‌​racterSet.URLQueryAl‌​lowedCharacterSet()
GetSwifty
  • 347
  • 2
  • 11
1

It may contain Zero-width-space, as the name suggests, it is a Unicode character, invisible to the naked eye

extension String {
    func replacePattern(pattern: String, replaceWith: String = "") -> String {
        do {
            let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options.caseInsensitive)
            let range = NSMakeRange(0, self.count)
            return regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: replaceWith)
        } catch {
            return self
        }
    }
    
    var fixZeroWidthSpace: String {
        addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)?.replacePattern(pattern: "%E2%80%8B", replaceWith: "") ?? ""
    }
}

let url = urlString.fixZeroWidthSpace 
Tema Tian
  • 331
  • 3
  • 12
0

URLComponents is meant to dodge the hell of manual escaping of url components (for each different rules apply)

public func configure()
{
    if var urc = URLComponents(string: "https://fake/") {
        urc.host = your real hostname with whatever characters are not allowed in hostname
        ... same deal for other url components
        YourScope.baseUrlPath = urc.url?.absoluteString
    }
}
Anton Tropashko
  • 5,486
  • 5
  • 41
  • 66
0

I’m not sure it would help your specific situation, but I had a similar set of symptoms and the cause(after so much frustration) was just blank spaces in the long url with an API key and stuff. As suggested by “@workingdog support Ukraine” I added in % in the blanks and it worked. (Note: it was on a date/time part of a long api url the % was inserted into my code so idk if it applies to dates specifically or the entire url) Anyway this might help someone else. Be blessed

Z3phyr
  • 1
  • 4