'How to insert space in URL based off user input

I make a call to a food api that has a query based off user input.

How can I detect if a user enters a space in their search (ie. if they search for a word like "Whey Protein".

  func searchFood(userItem: String){
       //calls api search
        guard let url = URL(string: "https://api.nal.usda.gov/fdc/v1/foods/search?&api_key=bRbzV****y8cqG&query=\(userItem)") else {return}
        
        URLSession.shared.dataTask(with: url) { (data, _,_) in
            let searchResults = try! JSONDecoder().decode(APISearchResults.self, from: data!)
            
            DispatchQueue.main.async {
                for item in searchResults.foods ?? []{
                   self.foodDescription = item.lowercaseDescription?.firstCapitalized ?? "food not valid"
                    self.calories = String(Double(round(item.foodNutrients?[3].value! ?? 0.00)).removeZerosFromEnd())
                    self.brand = item.brandOwner ?? "General"
                   
                    }
               
                }
        }
        .resume()
    }


Solution 1:[1]

As @Larme said in their comment, you should use URL encoding to add spaces in URL query items.

To convert an existing string to percent/url encoding, you can use the following snippet (obtained from this SO question):

yourString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

They also stated that you should use URLQueryItem to construct your URLs and to add to this, I recommend you to use this extension to construct URLs easily.

extension URL {

    /// Adds a query item to a URL
    public func queryItem(_ queryItem: String, value: String?) -> URL {
        guard var urlComponents = URLComponents(string: absoluteString) else { return absoluteURL }
        var queryItems: [URLQueryItem] = urlComponents.queryItems ??  []
        let queryItem = URLQueryItem(name: queryItem, value: value)
        queryItems.append(queryItem)
        urlComponents.queryItems = queryItems
        return urlComponents.url!
    }
    
    /// Retrieves the query items of a URL
    public var queryParameters: [String: String]? {
        guard
            let components = URLComponents(url: self, resolvingAgainstBaseURL: true),
            let queryItems = components.queryItems else { return nil }
        return queryItems.reduce(into: [String: String]()) { (result, item) in
            result[item.name] = item.value
        }
    }

}

And, when constructing your URL, you can use this:

url = url.queryItem("key", value: "value")

References:

Percent-encoding. (2022, March 31). In Wikipedia. https://en.wikipedia.org/wiki/Percent-encoding

zaph & Oleander, L. (2014, July 3). Swift - encode URL. Stack Overflow. Retrieved April 18, 2022, from Swift - encode URL

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1