Réponses:
Malheureusement, stringByAddingPercentEscapesUsingEncoding
cela ne fonctionne pas toujours à 100%. Il encode les caractères non URL mais laisse les caractères réservés (comme la barre oblique /
et l'esperluette &
) seuls. Apparemment, c'est un bogue dont Apple est conscient, mais comme ils ne l'ont pas encore corrigé, j'utilise cette catégorie pour encoder une chaîne en url:
@implementation NSString (NSString_Extended)
- (NSString *)urlencode {
NSMutableString *output = [NSMutableString string];
const unsigned char *source = (const unsigned char *)[self UTF8String];
int sourceLen = strlen((const char *)source);
for (int i = 0; i < sourceLen; ++i) {
const unsigned char thisChar = source[i];
if (thisChar == ' '){
[output appendString:@"+"];
} else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' ||
(thisChar >= 'a' && thisChar <= 'z') ||
(thisChar >= 'A' && thisChar <= 'Z') ||
(thisChar >= '0' && thisChar <= '9')) {
[output appendFormat:@"%c", thisChar];
} else {
[output appendFormat:@"%%%02X", thisChar];
}
}
return output;
}
Utilisé comme ceci:
NSString *urlEncodedString = [@"SOME_URL_GOES_HERE" urlencode];
// Or, with an already existing string:
NSString *someUrlString = @"someURL";
NSString *encodedUrlStr = [someUrlString urlencode];
Cela fonctionne également:
NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8 );
Quelques bonnes lectures sur le sujet:
Objectif-c iPhone pour cent encoder une chaîne?
Encodage URL Objective-C et Swift
http://cybersam.com/programming/proper-url-percent-encoding-in-ios
https://devforums.apple.com/message/15674#15674
http://simonwoodside.com/weblog/2009/4/ 22 / how_to_really_url_encode /
Cela pourrait être utile
NSString *sampleUrl = @"http://www.google.com/search.jsp?params=Java Developer";
NSString* encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding];
Pour iOS 7+, la méthode recommandée est:
NSString* encodedUrl = [sampleUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
Vous pouvez choisir le jeu de caractères autorisé selon les exigences du composant URL.
-stringByAddingPercentEncodingWithAllowedCharacters:
place, qui utilise toujours le codage UTF-8 recommandé et qui code pour un composant ou sous-composant URL spécifique, car chaque composant ou sous-composant URL a des règles différentes pour les caractères valides."
De nouvelles API ont été ajoutées depuis que la réponse a été sélectionnée; Vous pouvez maintenant utiliser NSURLUtilities. Étant donné que différentes parties des URL autorisent différents caractères, utilisez le jeu de caractères applicable. L'exemple suivant code pour l'inclusion dans la chaîne de requête:
encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
Pour convertir spécifiquement «&», vous devez le supprimer de l'ensemble de requêtes URL ou utiliser un ensemble différent, car «&» est autorisé dans une requête URL:
NSMutableCharacterSet *chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;
[chars removeCharactersInRange:NSMakeRange('&', 1)]; // %26
encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:chars];
NSMakeRange('&', 1)
ne fonctionne pas dans Swift, car Swift n'autorise pas la conversion de caractères en int sans hacks. Pour utiliser cette solution en code Swift, utilisez à la removeCharactersInString("&")
place de.removeCharactersInRange(...)
Exemple de Swift 2.0 (compatible avec iOS 9)
extension String {
func stringByURLEncoding() -> String? {
let characters = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet
characters.removeCharactersInString("&")
guard let encodedString = self.stringByAddingPercentEncodingWithAllowedCharacters(characters) else {
return nil
}
return encodedString
}
}
mise à jour ios 7
NSString *encode = [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *decode = [encode stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
J'ai choisi d'utiliser l' CFURLCreateStringByAddingPercentEscapes
appel tel que donné par la réponse acceptée, mais dans la dernière version de XCode (et IOS), cela a entraîné une erreur, j'ai donc utilisé ce qui suit à la place:
NSString *apiKeyRaw = @"79b|7Qd.jW=])(fv|M&W0O|3CENnrbNh4}2E|-)J*BCjCMrWy%dSfGs#A6N38Fo~";
NSString *apiKey = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)apiKeyRaw, NULL, (CFStringRef)@"!*'();:@&=+$,/?%#[]", kCFStringEncodingUTF8));
Essayez d'utiliser la stringByAddingPercentEncodingWithAllowedCharacters
méthode avec [NSCharacterSet URLUserAllowedCharacterSet]
elle couvrira tous les cas
Objectif c
NSString *value = @"Test / Test";
value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLUserAllowedCharacterSet]];
rapide
var value = "Test / Test"
value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLUserAllowedCharacterSet())
Production
Test%20%2F%20Test
Après avoir lu toutes les réponses à ce sujet et la ( mauvaise ) acceptée, je veux ajouter ma contribution.
SI la cible est iOS7 +, et en 2017, cela devrait, puisque XCode rend vraiment difficile la compatibilité sous iOS8, le meilleur moyen, sûr pour les threads, rapide, amd prendra entièrement en charge UTF-8 pour ce faire est:
(Code objectif C)
@implementation NSString (NSString_urlencoding)
- (NSString *)urlencode {
static NSMutableCharacterSet *chars = nil;
static dispatch_once_t pred;
if (chars)
return [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
// to be thread safe
dispatch_once(&pred, ^{
chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;
[chars removeCharactersInString:@"!*'();:@&=+$,/?%#[]"];
});
return [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
}
@end
Cela étendra NSString, exclura les caractères interdits RFC, prendra en charge les caractères UTF-8 et vous permettra d'utiliser des choses comme:
NSString *myusername = "I'm[evil]&want(to)break!!!$->àéìòù";
NSLog(@"Source: %@ -> Dest: %@", myusername, [myusername urlencode]);
Cela s'imprimera sur votre console de débogage:
Source: I'm [evil] & want (to) break !!! $ -> àéìòù -> Dest: I% 27m% 5Bevil% 5D% 26want% 28to% 29break% 21% 21% 21% 24-% 3E% C3 % A0% C3% A9% C3% AC% C3% B2% C3% B9
... notez également l'utilisation de dispatch_once pour éviter de multiples initialisations dans les environnements multithread.
Voici une approche flexible prête pour la production dans Swift 5.x :
public extension CharacterSet {
static let urlQueryParameterAllowed = CharacterSet.urlQueryAllowed.subtracting(CharacterSet(charactersIn: "&?"))
static let urlQueryDenied = CharacterSet.urlQueryAllowed.inverted()
static let urlQueryKeyValueDenied = CharacterSet.urlQueryParameterAllowed.inverted()
static let urlPathDenied = CharacterSet.urlPathAllowed.inverted()
static let urlFragmentDenied = CharacterSet.urlFragmentAllowed.inverted()
static let urlHostDenied = CharacterSet.urlHostAllowed.inverted()
static let urlDenied = CharacterSet.urlQueryDenied
.union(.urlQueryKeyValueDenied)
.union(.urlPathDenied)
.union(.urlFragmentDenied)
.union(.urlHostDenied)
func inverted() -> CharacterSet {
var copy = self
copy.invert()
return copy
}
}
public extension String {
func urlEncoded(denying deniedCharacters: CharacterSet = .urlDenied) -> String? {
return addingPercentEncoding(withAllowedCharacters: deniedCharacters.inverted())
}
}
print("Hello, World!".urlEncoded()!)
print("You&Me?".urlEncoded()!)
print("#Blessed 100%".urlEncoded()!)
print("Pride and Prejudice".urlEncoded(denying: .uppercaseLetters)!)
Hello,%20World!
You%26Me%3F
%23Blessed%20100%25
%50ride and %50rejudice
Utilisez NSURLComponents pour coder les paramètres HTTP GET:
var urlComponents = NSURLComponents(string: "https://www.google.de/maps/")!
urlComponents.queryItems = [
NSURLQueryItem(name: "q", value: String(51.500833)+","+String(-0.141944)),
NSURLQueryItem(name: "z", value: String(6))
]
urlComponents.URL // returns https://www.google.de/maps/?q=51.500833,-0.141944&z=6
http://www.ralfebert.de/snippets/ios/encoding-nsurl-get-parameters/
Ce code m'a aidé à encoder des caractères spéciaux
NSString* encPassword = [password stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]];
code swift basé sur la réponse objc de chown dans ce fil.
extension String {
func urlEncode() -> String {
return CFURLCreateStringByAddingPercentEscapes(
nil,
self,
nil,
"!*'();:@&=+$,/?%#[]",
CFStringBuiltInEncodings.UTF8.rawValue
)
}
}
Dans Swift 3 , veuillez essayer ci-dessous:
let stringURL = "YOUR URL TO BE ENCODE";
let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(encodedURLString)
Depuis, stringByAddingPercentEscapesUsingEncoding
encode les caractères non URL mais laisse les caractères réservés (comme !*'();:@&=+$,/?%#[]
), vous pouvez encoder l'url comme le code suivant:
let stringURL = "YOUR URL TO BE ENCODE";
let characterSetTobeAllowed = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted)
if let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: characterSetTobeAllowed) {
print(encodedURLString)
}
Le conseil d'Apple, dans les notes de version 10.11, est:
Si vous devez encoder en pourcentage une chaîne d'URL entière, vous pouvez utiliser ce code pour encoder une NSString destinée à être une URL (dans urlStringToEncode):
NSString *percentEncodedURLString =
[[NSURL URLWithDataRepresentation:[urlStringToEncode dataUsingEncoding:NSUTF8StringEncoding] relativeToURL:nil] relativeString];
Dans mon cas où le dernier composant était des lettres arabes, j'ai fait ce qui suit dans 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;
}
}
usage:
let stringURL = "http://xxx.dev.com/endpoint/nonLatinCharacters"
if let encodedStringURL = stringURL.encodeUTF8() {
if let url = NSURL(string: encodedStringURL) {
...
}
}
-(NSString *)encodeUrlString:(NSString *)string {
return CFBridgingRelease(
CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(__bridge CFStringRef)string,
NULL,
CFSTR("!*'();:@&=+$,/?%#[]"),
kCFStringEncodingUTF8)
);
}
selon le blog suivant
Tant de réponses mais cela n'a pas fonctionné pour moi, alors j'ai essayé ce qui suit:
fun simpleServiceCall(for serviceUrl: String, appendToUrl: String) {
let urlString: String = serviceUrl + appendToUrl.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!
let finalUrl = URL(string: urlString)!
//continue to execute your service call...
}
J'espère que cela aidera quelqu'un. Merci
Pour les paramètres de requête codés par formulaire www, j'ai créé une catégorie sur NSString:
- (NSString*)WWWFormEncoded{
NSMutableCharacterSet *chars = NSCharacterSet.alphanumericCharacterSet.mutableCopy;
[chars addCharactersInString:@" "];
NSString* encodedString = [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
encodedString = [encodedString stringByReplacingOccurrencesOfString:@" " withString:@"+"];
return encodedString;
}
// Ceci est sans test
NSMutableCharacterSet* set = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
[set addCharactersInString:@"-_.~"];
NSString *encode = [test stringByAddingPercentEncodingWithAllowedCharacters:set];
J'ai rencontré un problème similaire en passant des chaînes complexes en tant que paramètre POST. Mes chaînes peuvent contenir des caractères asiatiques, des espaces, des guillemets et toutes sortes de caractères spéciaux. La solution que j'ai finalement trouvée a été de convertir ma chaîne dans la série correspondante d'Unicodes, par exemple "Hu0040Hu0020Hu03f5 ...." en utilisant [NSString stringWithFormat: @ "Hu% 04x", [string characterAtIndex: i]] pour obtenir l'Unicode de chaque caractère dans la chaîne d'origine. La même chose peut être faite en Java.
Cette chaîne peut être transmise en toute sécurité en tant que paramètre POST.
Côté serveur (PHP), je change tous les "H" en "\" et je passe la chaîne résultante à json_decode. La dernière étape consiste à échapper les guillemets simples avant de stocker la chaîne dans MySQL.
De cette façon, je peux stocker n'importe quelle chaîne UTF8 sur mon serveur.
Celui-ci fonctionne pour moi.
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
}
J'ai trouvé la fonction ci-dessus à partir de ce lien: http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/
Vous pouvez également utiliser cette fonction avec l'extension rapide. S'il vous plaît laissez-moi savoir s'il y a un problème.