Свифт - кодировать URL-адрес
Если я кодирую строку следующим образом:
var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
он не избегает косых черт /.
Я искал и нашел этот объективный код C:
NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8 );
есть ли более простой способ кодировать URL-адрес, и если нет, как мне написать это в Swift?
10 ответов:
Swift 3
в Swift 3 есть
addingPercentEncodingvar originalString = "test/test" var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) print(escapedString!)выход:
тест%2Ftest
Swift 1
в iOS 7 и выше есть
stringByAddingPercentEncodingWithAllowedCharactersvar originalString = "test/test" var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet()) println("escapedString: \(escapedString)")выход:
тест%2Ftest
следующие полезные (инвертированные) наборы символов:
URLFragmentAllowedCharacterSet "#%<>[\]^`{|} URLHostAllowedCharacterSet "#%/<>?@\^`{|} URLPasswordAllowedCharacterSet "#%/:<>?@[\]^`{|} URLPathAllowedCharacterSet "#%;<>?[\]^`{|} URLQueryAllowedCharacterSet "#%<>[\]^`{|} URLUserAllowedCharacterSet "#%/:<>?@[\]^`если вы хотите, чтобы другой набор символов был экранирован, создайте набор:
Пример с добавлением символа"=":var originalString = "test/test=42" var customAllowedSet = NSCharacterSet(charactersInString:"=\"#%/<>?@\^`{|}").invertedSet var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(customAllowedSet) println("escapedString: \(escapedString)")выход:
тест%2Ftest%3D42
пример проверки символов ascii не в наборе:
func printCharactersInSet(set: NSCharacterSet) { var characters = "" let iSet = set.invertedSet for i: UInt32 in 32..<127 { let c = Character(UnicodeScalar(i)) if iSet.longCharacterIsMember(i) { characters = characters + String(c) } } print("characters not in set: \'\(characters)\'") }
Вы можете использовать URL-компоненты, чтобы избежать необходимости вручную проценты экранировать строку запроса:
let scheme = "https" let host = "www.google.com" let path = "/search" let queryItem = URLQueryItem(name: "q", value: "Formula One") var urlComponents = URLComponents() urlComponents.scheme = scheme urlComponents.host = host urlComponents.path = path urlComponents.queryItems = [queryItem] if let url = urlComponents.url { print(url) // "https://www.google.com/search?q=Formula%20One" }
extension URLComponents { init(scheme: String, host: String, path: String, queryItems: [URLQueryItem]) { self.init() self.scheme = scheme self.host = host self.path = path self.queryItems = queryItems } } if let url = URLComponents(scheme: "https", host: "www.google.com", path: "/search", queryItems: [URLQueryItem(name: "q", value: "Formula One")]).url { print(url) // https://www.google.com/search?q=Formula%20One }
Swift 3:
let allowedCharacterSet = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted) if let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) { //do something with escaped string }
Swift 3:
let originalString = "http://www.ihtc.cc?name=htc&title=iOS开发工程师"1. encodingQuery:
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)результат:
"http://www.ihtc.cc?name=htc&title=iOS%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88"
2. кодировка:
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)результат:
"http:%2F%2Fwww.ihtc.cc%3Fname=htc&title=iOS%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88"
все то же самое
var str = CFURLCreateStringByAddingPercentEscapes( nil, "test/test", nil, "!*'();:@&=+$,/?%#[]", CFStringBuiltInEncodings.UTF8.rawValue ) // test%2Ftest
Swift 4
для кодирования параметра в URL я нахожу с помощью
.alphanumericsнабор символов самый простой вариант:let encoded = parameter.addingPercentEncoding(withAllowedCharacters: .alphanumerics) let url = "http://www.example.com/?name=\(encoded!)"использование любого из стандартных наборов символов для кодирования URL (например,
URLQueryAllowedCharacterSetилиURLHostAllowedCharacterSet) не будет работать, потому что они не исключают=или&символы.Примечание что с помощью
.alphanumericsон будет кодировать некоторые символы, которые не нужно кодировать (например,-,.,_или~-- см. 2.3. Незащищенные символы в RFC 3986). Я нахожу с помощью.alphanumericsпроще, чем создание пользовательского набора символов и не возражают некоторые дополнительные символы для кодирования. Если это вас беспокоит, создайте пользовательский набор символов, как описано в как проценты кодируют строку URL, например:var allowed = CharacterSet.alphanumerics allowed.insert(charactersIn: "-._~") // as per RFC 3986 let encoded = parameter.addingPercentEncoding(withAllowedCharacters: allowed) let url = "http://www.example.com/?name=\(encoded!)"предупреждение: The
encodedпараметр сила развернута. Для недопустимой строки unicode это может привести к сбою. Смотрите почему возвращаемое значение String.addingPercentEncoding () необязательно?. Вместо того, чтобы силой разворачиватьencoded!можно использоватьencoded ?? ""или использоватьif let encoded = ....
Swift 4 (не тестировался - пожалуйста, прокомментируйте, если он работает или нет. Спасибо @sumizome за предложение)
var allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed allowedQueryParamAndKey.remove(charactersIn: ";/?:@&=+$, ") paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)Swift 3
let allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed.remove(charactersIn: ";/?:@&=+$, ") paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)Swift 2.2 (заимствование из Zaph и исправление для ключа запроса url и значений параметров)
var allowedQueryParamAndKey = NSCharacterSet(charactersInString: ";/?:@&=+$, ").invertedSet paramOrKey.stringByAddingPercentEncodingWithAllowedCharacters(allowedQueryParamAndKey)пример:
let paramOrKey = "https://some.website.com/path/to/page.srf?a=1&b=2#top" paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey) // produces: "https%3A%2F%2Fsome.website.com%2Fpath%2Fto%2Fpage.srf%3Fa%3D1%26b%3D2%23top"Это более короткая версия ответа Брайана Чена. Я бы предположил, что
urlQueryAllowedпозволяет управлять символами через это нормально, если они не являются частью ключа или значения в строке запроса, в которой они должны быть экранированы.
Swift 4:
это зависит от правил кодирования, за которыми следует ваш сервер.
Apple предлагает этот метод класса, но он не сообщает, какой протокол RCF он следует.
var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!после этого полезно инструмент вы должны гарантировать кодирования этих символов для ваших параметров:
- $ (знак доллара) становится %24
- & (амперсанд) становится %26
- + (Плюс) будет %2B
- , (запятая) становится %2C
- : (двоеточие) становится %3A
- ; (точка с запятой) становится %3B
- = (равно) становится %3D
- ? (Вопросительный знак) становится %3F
- @ (коммерческий A / At) становится %40
другими словами, говоря о кодировке URL, вы должны следовать протокол RFC 1738.
и Swift не покрывают кодировку + char для пример, но он хорошо работает с этими тремя @:? chars.
Итак, чтобы правильно кодировать каждый ваш параметр, то
.urlHostAllowedопция не достаточно, вы должны добавить также специальные символы, как например:encodedParameter = parameter.replacingOccurrences(of: "+", with: "%2B")надеюсь, что это помогает кто-то, кто сошел с ума, чтобы искать эту информацию.
мне самому это было нужно, поэтому я написал расширение строки, которое позволяет как для строк URLEncoding, так и для более общей конечной цели, Преобразуя словарь параметров в Параметры URL-адреса стиля "GET":
extension String { func URLEncodedString() -> String? { var escapedString = self.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) return escapedString } static func queryStringFromParameters(parameters: Dictionary<String,String>) -> String? { if (parameters.count == 0) { return nil } var queryString : String? = nil for (key, value) in parameters { if let encodedKey = key.URLEncodedString() { if let encodedValue = value.URLEncodedString() { if queryString == nil { queryString = "?" } else { queryString! += "&" } queryString! += encodedKey + "=" + encodedValue } } } return queryString } }наслаждайтесь!
этот работает на меня.
func stringByAddingPercentEncodingForFormData(plusForSpace: Bool=false) -> String? { let unreserved = "*-._" let allowed = NSMutableCharacterSet.alphanumericCharacterSet() allowed.addCharactersInString(unreserved) if plusForSpace { allowed.addCharactersInString(" ") } var encoded = stringByAddingPercentEncodingWithAllowedCharacters(allowed) if plusForSpace { encoded = encoded?.stringByReplacingOccurrencesOfString(" ", withString: "+") } return encoded }Я нашел выше функцию по этой ссылке:http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/.
Comments