Search code examples
swiftui

Add URL parameters in Swift share sheet


I have this code

Button(action: {
    let url = URL(string: "https://example.com/deeplink.html?addfriend&user=admin")
    let message = "Come play with me: \(url)"
    let smsURL = "sms:&body=\(message.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")"

    if let url = URL(string: smsURL), UIApplication.shared.canOpenURL(url) {
         UIApplication.shared.open(url, options: [:], completionHandler: nil)
    } else {
         print("Cannot open SMS app")
    }
}) {
    VStack {
        Text("Message")
            .font(.poppinsFootnote.bold())
            .foregroundColor(.white)
    }
}

However, the url appears without the paramaters and the message is cut off. Seems like the special characters are not allowed? How do I fix such issue?


Solution

  • Characters such as & and = are allowed in URL queries, but they have special meaning. Therefore, addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) is not enough to sanitise the string. You will end up with a URL query like this:

    body=Come%20play%20with%20me:%20https://example.com/deeplink.html?addfriend&user=admin
    

    The query "addfriend&user=admin" is treated as part of the query for the "sms:" URL, instead of literally as part of the body. This is why the query (and everything after it) is gone when the Messages app is opened.

    You can use

    message.addingPercentEncoding(withAllowedCharacters: [])
    

    to percent-encode everything in message.

    Or, use the URLComponents API which automatically encodes everything correctly.

    var components = URLComponents()
    components.scheme = "sms"
    components.queryItems = [
        .init(name: "body", value: message)
    ]
    if let smsURL = components.url?.absoluteString {
        // ...
    }