URL Кодирование строки специальными символами - PullRequest
0 голосов
/ 24 мая 2018

Пожалуйста, рассмотрите код ниже, который я реализовал в моем приложении для iOS:

let kBaseURL = "https://www.sampledomain.com/"
let method = "api/MasterData/GetCompanyList?jsonArgs={\"AccountID\":%d}"

private func prepareURL(api: String) -> String {
    return (kBaseURL + api).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
}

В коде выше, у "method" есть "% d", который будет заменен идентификатором учетной записи (во время выполнения), которыйцелое число.

let accountID = 20
let methodToCall = String(format: method, accountID)
var apiRequest = URLRequest(url: URL(string: prepareURL(api: methodToCall))!)

Приведенный выше код вызывает сбой, поскольку URL-адрес равен nil из-за «метода» со специальными символами в нем.

Причина сбоя, заданная Xcode: Поток 1: фатальная ошибка: неожиданно обнаружен ноль при развертывании необязательного значения

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Как указано в Apple doc , если в строке есть несколько символов, которые недопустимы в URL, URL (строка :) возвращает ноль.В этом случае вам нужно% кодировать следующим образом.

let url = URL(string: "123\"456") // this returns nil due to double quote

Поэтому вам нужно mofify к

let url = URL(string: "123\"456".addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!)

Я столкнулся с той же проблемой, когда обрабатывал неанглийские буквы;для моего случая они "кандзи".Поэтому я всегда использую процентное кодирование без проверки содержимого строки при вызове URL (строка :).На самом деле, существует так много нелегальных URL-букв с кандзи, и почти невозможно проверить, что является законным, а что нет, вручную.URL (строка :) с процентной строкой при добавлении PercentEncoding (withAllowedCharacters: .urlHostAllowed) всегда хорошо работает для меня.

0 голосов
/ 24 мая 2018

Вам необходимо также закодировать эти символы.Вы можете проверить, какие процентные значения экранированы для { и }, и ввести их вручную.Но я предпочитаю, чтобы у вас была возможность создать строку запроса из словаря.Что-то вроде следующего должно решить вашу проблему:

func createQueryString(from parameters: [String: String]) -> String {
    let components: [String] = parameters.compactMap { item in
        guard let encoded = item.value.addingPercentEncoding(withAllowedCharacters: CharacterSet(charactersIn: "!*'\"(){};:@&=+$,/?%#[]% ").inverted) else { return nil }
        return item.key + "=" + encoded
    }
    return components.joined(separator: "&")
}

Теперь все, что вам нужно сделать, это использовать его и убедиться, что jsonArgs={\"AccountID\":%d} также используется в словаре.Попробуйте что-то вроде:

func generateAccountsRequest(accountID: Int) -> URLRequest {
    let kBaseURL = "https://www.sampledomain.com"
    let endpoint = "api/MasterData/GetCompanyList"

    func prepareURL(endpoint: String, query: [String: String]) -> String {
        return kBaseURL + "/" + endpoint + "?" + createQueryString(from: query)
    }

    return URLRequest(url: URL(string: prepareURL(endpoint: endpoint, query: ["jsonArgs": "{\"AccountID\":\(accountID)}"]))!)
}
...