Свифт - кодировать URL-адрес



Если я кодирую строку следующим образом:



var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)


он не избегает косых черт /.



Я искал и нашел этот объективный код C:



NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8 );


есть ли более простой способ кодировать URL-адрес, и если нет, как мне написать это в Swift?

892   10  

10 ответов:

Swift 3

в Swift 3 есть addingPercentEncoding

var originalString = "test/test"
var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(escapedString!)

выход:

тест%2Ftest

Swift 1

в iOS 7 и выше есть stringByAddingPercentEncodingWithAllowedCharacters

var 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

    Ничего не найдено.