![]() |
飞奔的灯泡 · 【文明城市创建巡礼】昆明:新风吹满地 春城更美丽· 9 月前 · |
![]() |
暴躁的李子 · 李肇星夫妇在冀州|外交部|秦小梅_网易订阅· 9 月前 · |
![]() |
霸气的弓箭 · 中国驻法兰克福总领馆启用“中国领事”APP护 ...· 1 年前 · |
![]() |
乐观的长颈鹿 · 趣书网怎么又打不开了? - 知乎· 1 年前 · |
![]() |
失恋的汽水 · 漫威主线漫画故事《蜘蛛末日》:一段悲壮的嗜血 ...· 1 年前 · |
如果我像这样编码一个字符串:
var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
它不能逃脱斜杠
/
。
我搜索并找到了这个目标C代码:
NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8 );
是否有一种更简单的方式来编码一个URL,如果不是,我如何用Swift写这个呢?
Swift 3
在Swift 3中有
addingPercentEncoding
let originalString = "test/test"
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(escapedString!)
输出:
测试%2 2Ftest
Swift 1
在iOS 7及以上版本中,有
stringByAddingPercentEncodingWithAllowedCharacters
var originalString = "test/test"
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
println("escapedString: \(escapedString)")
输出:
测试%2 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)")
输出:
测试%2 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)\'")
}
一切都是一样的
var str = CFURLCreateStringByAddingPercentEscapes(
"test/test",
"!*'();:@&=+$,/?%#[]",
CFStringBuiltInEncodings.UTF8.rawValue
// test%2Ftest
我自己也需要这样做,所以我编写了一个字符串扩展,它既允许URLEncoding字符串,也允许更常见的最终目标,将参数字典转换为"GET“样式的URL参数:
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 = "?"
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/ 。
Swift 4&5(感谢@sumizome的建议)。谢谢@FD_和@derickito的测试)
var allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed
allowedQueryParamAndKey.remove(charactersIn: ";/?:@&=+$, ")
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)
Swift 3
let allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed.remove(charactersIn: ";/?:@&=+$, ")
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)
SWIFT2.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 5:
extension String {
var urlEncoded: String? {
let allowedCharacterSet = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "~-_."))
return self.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet)
print("\u{48}ello\u{9}world\u{7}\u{0}".urlEncoded!) // prints Hello%09world%07%00
print("The string ü@foo-bar".urlEncoded!) // prints The%20string%20%C3%BC%40foo-bar
您可以使用URLComponents来避免手动编码查询字符串的百分比:
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 = "https",
host: String = "www.google.com",
path: String = "/search",
queryItems: [URLQueryItem]) {
self.init()
self.scheme = scheme
self.host = host
self.path = path
self.queryItems = queryItems
}
let query = "Formula One"
if let url = URLComponents(queryItems: [URLQueryItem(name: "q", value: query)]).url {
print(url) // https://www.google.com/search?q=Formula%20One
}
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. encodingURL:
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"
Swift 4:
这取决于您的服务器遵循的编码规则。
Apple提供了这个类方法,但是它没有报告它遵循的那种RCF协议。
var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
遵循这个有用的 工具 ,您应该保证参数的这些字符的编码:
换句话说,谈到URL编码,您应该遵循 RFC 1738协议 。
和Swift不包括+ char (例如 )的编码,但是它可以很好地处理这三个 @:? 字符。
因此,要正确编码每个参数,
.urlHostAllowed
选项是不够的,您还应该添加一些特殊的字符,例如:
encodedParameter = parameter.replacingOccurrences(of: "+", with: "%2B")
希望这能帮助那些疯狂地搜索这些信息的人。
Swift 4&5
要在URL中编码参数,我发现使用
.alphanumerics
字符集是最简单的选项:
let urlEncoded = value.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
let url = "http://www.example.com/?name=\(urlEncoded!)"
使用任何用于URL编码的标准字符集(如
.urlQueryAllowed
或
.urlHostAllowed
)都不起作用,因为它们不排除
=
或
&
字符。
注意到
,通过使用
.alphanumerics
,它将编码一些不需要编码的字符(比如
-
、
.
、
_
或
~
--参见2.3 )。RFC 3986中的无保留字符)。我发现使用
.alphanumerics
比构建自定义字符集更简单,并且不介意要编码的其他字符。如果这让您感到困扰,请按照
如何对URL字符串进行百分比编码
中的描述构造一个自定义字符集,例如:
// Store allowed character set for reuse (computed lazily).
private let urlAllowed: CharacterSet =
.alphanumerics.union(.init(charactersIn: "-._~")) // as per RFC 3986
extension String {
var urlEncoded: String? {
return addingPercentEncoding(withAllowedCharacters: urlAllowed)
let url = "http://www.example.com/?name=\(value.urlEncoded!)"
警告:
--
urlEncoded
参数是强制展开的。对于无效的unicode字符串,它可能会崩溃。见
为什么String.addingPercentEncoding()的返回值是可选的?
。与强制展开
urlEncoded!
不同,您可以使用
urlEncoded ?? ""
或
if let urlEncoded = urlEncoded { ... }
。
这是在
Swift 5
为我工作。用例是从剪贴板或类似的地方获取一个URL,该剪贴板可能已经有转义字符,但也包含可能导致
URLComponents
或
URL(string:)
失败的Unicode字符。
首先,创建一个包含所有URL合法字符的字符集:
extension CharacterSet {
/// Characters valid in at least one part of a URL.
/// These characters are not allowed in ALL parts of a URL; each part has different requirements. This set is useful for checking for Unicode characters that need to be percent encoded before performing a validity check on individual URL components.
static var urlAllowedCharacters: CharacterSet {
// Start by including hash, which isn't in any set
var characters = CharacterSet(charactersIn: "#")
// All URL-legal characters
characters.formUnion(.urlUserAllowed)
characters.formUnion(.urlPasswordAllowed)
characters.formUnion(.urlHostAllowed)
characters.formUnion(.urlPathAllowed)
characters.formUnion(.urlQueryAllowed)
characters.formUnion(.urlFragmentAllowed)
return characters
}
接下来,用一个方法对
String
进行扩展,以编码URL:
extension String {
/// Converts a string to a percent-encoded URL, including Unicode characters.
/// - Returns: An encoded URL if all steps succeed, otherwise nil.
func encodedUrl() -> URL? {
// Remove preexisting encoding,
guard let decodedString = self.removingPercentEncoding,
// encode any Unicode characters so URLComponents doesn't choke,
let unicodeEncodedString = decodedString.addingPercentEncoding(withAllowedCharacters: .urlAllowedCharacters),
// break into components to use proper encoding for each part,
let components = URLComponents(string: unicodeEncodedString),
// and reencode, to revert decoding while encoding missed characters.
let percentEncodedUrl = components.url else {
// Encoding failed
return nil
return percentEncodedUrl
}
它可以测试如下:
let urlText = "https://www.example.com/폴더/search?q=123&foo=bar&multi=eggs+and+ham&hangul=한글&spaced=lovely%20spam&illegal=<>#top"
let url = encodedUrl(from: urlText)
结尾处的
url
值:
https://www.example.com/%ED%8F%B4%EB%8D%94/search?q=123&foo=bar&multi=eggs+and+ham&hangul=%ED%95%9C%EA%B8%80&spaced=lovely%20spam&illegal=%3C%3E#top
请注意,
%20
和
+
间距都保持不变,Unicode字符被编码,原始
urlText
中的
%20
不是双重编码的,锚点(片段或
#
)保持不变。
编辑: 现在检查每个组件的有效性。
SWIFT 4.2
有时发生这种情况仅仅是因为段塞中有空间,或者没有通过API传递参数的URL编码。
let myString = self.slugValue
let csCopy = CharacterSet(bitmapRepresentation: CharacterSet.urlPathAllowed.bitmapRepresentation)
let escapedString = myString!.addingPercentEncoding(withAllowedCharacters: csCopy)!
//always "info:hello%20world"
print(escapedString)
注意:不要忘记探索有关
bitmapRepresentation
的内容。
Swift 4.2
一个快速的单行解决方案。用要编码的字符串替换
originalString
。
var encodedString = originalString.addingPercentEncoding(withAllowedCharacters: CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[]{} ").inverted)
let Url = URL(string: urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")
用于Swift 5的 对字符串 的尾码
func escape(string: String) -> String {
let allowedCharacters = string.addingPercentEncoding(withAllowedCharacters: CharacterSet(charactersIn: ":=\"#%/<>?@\\^`{|}").inverted) ?? ""
return allowedCharacters
}
如何使用?
let strEncoded = self.escape(string: "http://www.edamam.com/ontologies/edamam.owl#recipe_e2a1b9bf2d996cbd9875b80612ed9aa4")
print("escapedString: \(strEncoded)")
这些答案对我都没有用。当一个网址包含非英语字符时,我们的应用程序崩溃了。
let unreserved = "-._~/?%$!:"
let allowed = NSMutableCharacterSet.alphanumeric()
allowed.addCharacters(in: unreserved)
let escapedString = urlString.addingPercentEncoding(withAllowedCharacters: allowed as CharacterSet)
根据您要做的操作的参数,您可能只想创建您自己的字符集。以上允许使用英文字符和
-._~/?%$!:
。
帮助我的是,我创建了一个单独的
NSCharacterSet
,并将其用于UTF-8编码字符串,即
textToEncode
来生成所需的结果:
var queryCharSet = NSCharacterSet.urlQueryAllowed
queryCharSet.remove(charactersIn: "+&?,:;@+=$*()")
let utfedCharacterSet = String(utf8String: textToEncode.cString(using: .utf8)!)!
let encodedStr = utfedCharacterSet.addingPercentEncoding(withAllowedCharacters: queryCharSet)!
let paramUrl = "https://api.abc.eu/api/search?device=true&query=\(escapedStr)"
![]() |
飞奔的灯泡 · 【文明城市创建巡礼】昆明:新风吹满地 春城更美丽 9 月前 |
![]() |
暴躁的李子 · 李肇星夫妇在冀州|外交部|秦小梅_网易订阅 9 月前 |
![]() |
乐观的长颈鹿 · 趣书网怎么又打不开了? - 知乎 1 年前 |