在iOS9中替换stringByAddingPercentEscapesUsingEncoding?


112

在iOS8及更低版本中,我可以使用:

NSString *str = ...; // some URL
NSString *result = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

在iOS9中stringByAddingPercentEscapesUsingEncoding已被替换为stringByAddingPercentEncodingWithAllowedCharacters

NSString *str = ...; // some URL
NSCharacterSet *set = ???; // where to find set for NSUTF8StringEncoding?
NSString *result = [str stringByAddingPercentEncodingWithAllowedCharacters:set];

我的问题是:在哪里可以找到需要的NSCharacterSetNSUTF8StringEncoding),以适当替换stringByAddingPercentEscapesUsingEncoding

Answers:


131

弃用消息说(强调我):

请改用stringByAddingPercentEncodingWithAllowedCharacters(_ :),它始终使用建议的UTF-8编码,并且对特定的URL组件或子组件进行编码,因为每个URL组件或子组件对有效字符的使用规则有所不同。

因此,您只需要提供足够NSCharacterSet的参数即可。幸运的是,对于URL,有一个非常方便的类方法URLHostAllowedCharacterSet,您可以像这样使用:

let encodedHost = unencodedHost.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())

Swift 3的更新-该方法成为静态属性urlHostAllowed

let encodedHost = unencodedHost.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

但是请注意:

此方法旨在对URL组件或子组件字符串(而非整个URL字符串)进行百分比编码。


6
另外,我强烈建议您使用NSURLComponents,它可以为您处理百分比编码。
Antonio Favata 2015年

1
对于整个URL字符串使用什么建议?
技能M2

1
@ SkillM2我认为NSURLComponents(每个组件都用相应的百分比编码NSCharacterSet)是正确的方法。
Antonio Favata 2015年

2
您永远都不要尝试对整个URL字符串进行编码。它可能导致意外的错误,在某些情况下还可能导致安全漏洞。唯一可以保证对URL进行编码的正确方法是一次执行一次。
dgatwood '16

大。非常感谢,队友!
费利佩

100

对于Objective-C:

NSString *str = ...; // some URL
NSCharacterSet *set = [NSCharacterSet URLHostAllowedCharacterSet]; 
NSString *result = [str stringByAddingPercentEncodingWithAllowedCharacters:set];

在哪里可以找到NSUTF8StringEncoding的集合?

有六个URL组件和子组件的预定义字符集,它们允许百分比编码。这些字符集传递给 -stringByAddingPercentEncodingWithAllowedCharacters:

 // Predefined character sets for the six URL components and subcomponents which allow percent encoding. These character sets are passed to -stringByAddingPercentEncodingWithAllowedCharacters:.
@interface NSCharacterSet (NSURLUtilities)
+ (NSCharacterSet *)URLUserAllowedCharacterSet;
+ (NSCharacterSet *)URLPasswordAllowedCharacterSet;
+ (NSCharacterSet *)URLHostAllowedCharacterSet;
+ (NSCharacterSet *)URLPathAllowedCharacterSet;
+ (NSCharacterSet *)URLQueryAllowedCharacterSet;
+ (NSCharacterSet *)URLFragmentAllowedCharacterSet;
@end

弃用消息说(强调我):

请改用stringByAddingPercentEncodingWithAllowedCharacters(_ :),它始终使用建议的UTF-8编码,并且对特定的URL组件或子组件进行编码,因为每个URL组件或子组件对有效字符的使用规则有所不同。

因此,您只需要提供足够NSCharacterSet的参数即可。幸运的是,对于URL,有一个非常方便的类方法URLHostAllowedCharacterSet,您可以像这样使用:

NSCharacterSet *set = [NSCharacterSet URLHostAllowedCharacterSet]; 

但是请注意:

此方法旨在对URL组件或子组件字符串(而非整个URL字符串)进行百分比编码。


4
当苹果让生活更轻松时,我会喜欢。谢谢苹果。
鸭子

5
“此方法旨在对URL组件或子组件字符串而不是整个URL字符串进行百分比编码”的含义是什么。?
GeneCode 2013年

4
URLHostAllowedCharacterSet给出错误“不受支持的URL”,我使用了URLFragmentAllowedCharacterSet,它的工作正常。
anoop4real

1
这不适用于+,不会对其进行编码,并且将被规范上的服务器端空间替换。
折腾

45

URLHostAllowedCharacterSet不工作对我来说。我URLFragmentAllowedCharacterSet改用。

目标-C

NSCharacterSet *set = [NSCharacterSet URLFragmentAllowedCharacterSet];
NSString * encodedString = [@"url string" stringByAddingPercentEncodingWithAllowedCharacters:set];

SWIFT-4

"url string".addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

以下是有用的(倒置)字符集:

URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}
URLHostAllowedCharacterSet      "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet     "#%<>[\]^`{|}
URLUserAllowedCharacterSet      "#%/:<>?@[\]^`

谢谢你,同样也一样
Arpit B Parekh

值得注意的是,这些集合都不包含+。因此,如果在查询参数中传递字符串,则字符串中的加号将被弄乱-在服务器端被视为空格``。
Asmo Soinio

21

目标C

此代码对我有用:

urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];

4

Swift 2.2:

extension String {
 func encodeUTF8() -> String? {
//If I can create an NSURL out of the string nothing is wrong with it
if let _ = NSURL(string: self) {

    return self
}

//Get the last component from the string this will return subSequence
let optionalLastComponent = self.characters.split { $0 == "/" }.last


if let lastComponent = optionalLastComponent {

    //Get the string from the sub sequence by mapping the characters to [String] then reduce the array to String
    let lastComponentAsString = lastComponent.map { String($0) }.reduce("", combine: +)


    //Get the range of the last component
    if let rangeOfLastComponent = self.rangeOfString(lastComponentAsString) {
        //Get the string without its last component
        let stringWithoutLastComponent = self.substringToIndex(rangeOfLastComponent.startIndex)


        //Encode the last component
        if let lastComponentEncoded = lastComponentAsString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.alphanumericCharacterSet()) {


        //Finally append the original string (without its last component) to the encoded part (encoded last component)
        let encodedString = stringWithoutLastComponent + lastComponentEncoded

            //Return the string (original string/encoded string)
            return encodedString
        }
    }
}

return nil;
}
}

2

对于Swift 3.0

您可以使用urlHostAllowedcharacterSet。

///返回主机URL子组件中允许的字符的字符集。

public static var urlHostAllowed: CharacterSet { get }

WebserviceCalls.getParamValueStringForURLFromDictionary(settingsDict as! Dictionary<String, AnyObject>).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed)

1

“此方法旨在对URL组件或子组件字符串而不是整个URL字符串进行百分比编码”的含义是什么。?– GeneCode 2013年9月1日8:30

这意味着您不应该编码https://xpto.example.com/path/subpathurl,而只能编码?

假设是因为在以下情况下有用例:

https://example.com?redirectme=xxxxx

xxxxx完全编码的URL 在哪里。


0

添加到接受的答案。考虑到此注释

此方法旨在对URL组件或子组件字符串(而非整个URL字符串)进行百分比编码。

整个网址不应编码:

let param = "=color:green|\(latitude),\(longitude)&\("zoom=13&size=\(width)x\(height)")&sensor=true&key=\(staticMapKey)".addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) 
let url = "https://maps.google.com/maps/api/staticmap?markers" + param!
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.