Search code examples
iosswiftstringnullqr-code

URL(string:) gives nil error even if the String is not nil in Swift


I have the following code:

print("CODE STRING SELECTED: \(codeString)")
let aURL = URL(string: codeString)!
if UIApplication.shared.canOpenURL(aURL) { UIApplication.shared.openURL(aURL) }

This code is inside a Button and the Xcode console prints the codeString correctly, it's not nil and so it should open the URL of the codeString, instead, Xcode throws this error:

CODE STRING SELECTED: mailto:john@doe.com?subject=Subject here&body=Lorem ipsum dolor sit, amet quatum.

Fatal error: Unexpectedly found nil while unwrapping an Optional value
2019-07-08 11:19:56.076467+0200 QRcode[2751:1043394] Fatal error: Unexpectedly found nil while unwrapping an Optional value

The same thing happens in case of a Phone number or SMS string (I get the codeString value from a scanned QR code):

CODE STRING SELECTED: tel:+1 2345678901
Fatal error: Unexpectedly found nil while unwrapping an Optional value

CODE STRING SELECTED: SMSTO:+1012345678:lorem ipsum dolor sit, amet
Fatal error: Unexpectedly found nil while unwrapping an Optional value

In case of a URL, like https//example.com, the app doesn't crash, no nil error, same for text, etc. So I really don't understand why I get that error even if the codeString is not nil.


Solution

  • The string is not nil but it does not represent a valid URL. You have to encode the URL.

    However it's recommended to unwrap the optionals safely

    if let encodedString = codeString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
       let aURL = URL(string: encodedString), UIApplication.shared.canOpenURL(aURL) { 
        UIApplication.shared.openURL(aURL) 
    }
    

    Update 2023:

    From the documentation of URL(string:)

    Important: For apps linked on or after iOS 17 and aligned OS versions, URL parsing has updated from the obsolete RFC 1738/1808 parsing to the same RFC 3986 parsing as URLComponents. This unifies the parsing behaviors of the URL and URLComponents APIs. Now, URL automatically percent- and IDNA-encodes invalid characters to help create a valid URL.