Encodage URL Objective-C et Swift

137

J'ai un NSStringcomme ça:

http://www.

mais je veux le transformer en:

http%3A%2F%2Fwww.

Comment puis-je faire ceci?

Usi Usi
la source
1
J'ai une chaîne cryptée comme ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~- aucune des solutions ci-dessous ne semble résoudre ce problème!
Mahendra Liya

Réponses:

324

Pour échapper aux personnages que vous voulez, c'est un peu plus de travail.

Exemple de code

iOS7 et supérieur:

NSString *unescaped = @"http://www";
NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSLog(@"escapedString: %@", escapedString);

Sortie NSLog:

escapedString: http% 3A% 2F% 2Fwww

Voici des jeux de caractères de codage d'URL utiles:

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

Création d'un jeu de caractères combinant tout ce qui précède:

NSCharacterSet *URLCombinedCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@" \"#%/:<>?@[\\]^`{|}"] invertedSet];

Créer un Base64

Dans le cas d'un jeu de caractères Base64:

NSCharacterSet *URLBase64CharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"/+=\n"] invertedSet];

Pour Swift 3.0:

var escapedString = originalString.addingPercentEncoding(withAllowedCharacters:.urlHostAllowed)

Pour Swift 2.x:

var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())

Remarque: stringByAddingPercentEncodingWithAllowedCharactersencodera également les caractères UTF-8 nécessitant un encodage.

Avant iOS7, utilisez Core Foundation à l'
aide de Core Foundation avec ARC:

NSString *escapedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
    NULL,
   (__bridge CFStringRef) unescaped,
    NULL,
    CFSTR("!*'();:@&=+$,/?%#[]\" "),
    kCFStringEncodingUTF8));

Utilisation de Core Foundation sans ARC:

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

Remarque: -stringByAddingPercentEscapesUsingEncodingne produira pas l'encodage correct, dans ce cas, il n'encodera rien retournant la même chaîne.

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding encode 14 caractères:

`#% ^ {} [] | \" <> plus le caractère d'espace sous forme de pourcentage échappé.

testString:

" `~!@#$%^&*()_+-={}[]|\\:;\"'<,>.?/AZaz"  

encodedString:

"%20%60~!@%23$%25%5E&*()_+-=%7B%7D%5B%5D%7C%5C:;%22'%3C,%3E.?/AZaz"  

Remarque: considérez si cet ensemble de caractères répond à vos besoins, sinon modifiez-les si nécessaire.

Caractères RFC 3986 nécessitant un encodage (% ajouté car il s'agit du caractère de préfixe d'encodage):

"! # $ & '() * +, /:; =? @ []%"

Certains "caractères non réservés" sont en outre codés:

"\ n \ r \"% -. <> \ ^ _ `{|} ~"

zaph
la source
1
Notez également que vous pouvez utiliser la -stringByAddingPercentEscapesUsingEncodingméthode de NSString .
Mike Weller du
2
Ah oui, maintenant je me souviens du stringByAddingPercentEscapesUsingEncodingcomportement funky . Il n'encode que «&» et «=» ou quelque chose de ridicule comme ça.
Mike Weller
2
Selon la RFC1738, vous devrez également encoder des caractères supplémentaires. Donc, bien que cela réponde à la question de l'OP, son utilité est limitée en tant qu'encodeur d'URL à usage général. Par exemple, il ne gère pas les éléments non alphanumériques tels qu'un tréma allemand.
Alex Nauda
3
Cela ne fonctionne pas (pour la partie iOS 7). Cela ne convertit pas & en% 26.
coolcool1994
1
Créez le jeu de caractères dont vous avez besoin à partir d'un NSStringavec characterSetWithCharactersInString, prenez l'inverse avec invertedSetet utilisez-le avec stringByAddingPercentEncodingWithAllowedCharacters. Pour un exemple, voir cette réponse SO .
zaph le
22

C'est ce qu'on appelle le codage d'URL . Plus ici .

-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
    return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
           (CFStringRef)self,
           NULL,
           (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
           CFStringConvertNSStringEncodingToEncoding(encoding));
}
larsaque
la source
3
Ce serait beaucoup plus utile si certains contenus des liens que vous avez publiés étaient inclus dans la réponse.
chown
1
CFURLCreateStringByAddingPercentEscapes()est obsolète. Utilisez [NSString stringByAddingPercentEncodingWithAllowedCharacters:]plutôt.
Pang
7

Ce n'est pas ma solution. Quelqu'un d'autre a écrit dans stackoverflow mais j'ai oublié comment.

D'une manière ou d'une autre, cette solution fonctionne "bien". Il gère les caractères diacritiques, chinois et à peu près tout le reste.

- (NSString *) URLEncodedString {
    NSMutableString * output = [NSMutableString string];
    const char * source = [self UTF8String];
    int sourceLen = strlen(source);
    for (int i = 0; i < sourceLen; ++i) {
        const unsigned char thisChar = (const unsigned char)source[i];
        if (false && 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;
}

Si quelqu'un me disait qui a écrit ce code, je l'apprécierais vraiment. En gros, il a une explication sur la raison pour laquelle cette chaîne encodée décodera exactement comme il le souhaite.

J'ai un peu modifié sa solution. J'aime que l'espace soit représenté avec% 20 plutôt que +. C'est tout.

Blanc anonyme
la source
qu'est-ce que [self UTF8String]?
Yuchao Zhou
1
@yuchaozh c'est une fonction que vous mettez dans une catégorie de NSString. Ainsi, self est NSStirng et [self UTF8String] renvoie, en supposant, sa chaîne au format UTF8.
Kelsey le
4
 NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NUL,(CFStringRef)@"parameter",NULL,(CFStringRef)@"!*'();@&+$,/?%#[]~=_-.:",kCFStringEncodingUTF8 );

NSURL * url = [[NSURL alloc] initWithString:[@"address here" stringByAppendingFormat:@"?cid=%@",encodedString, nil]];
Zahi
la source
1
release encodedString et url. ce code concerne le paramètre d'encodage. Pour encoder toute la chaîne de transmission d'adresse au lieu de "paramètre".
Zahi
Cela a fonctionné pour moi ... encodé même le caractère & avec lequel j'avais des problèmes.
Виктор Иванов
3

Cela peut fonctionner dans Objective C ARC.Utilisez CFBridgingRelease pour convertir un objet de style Core Foundation en objet Objective-C et transférer la propriété de l'objet à ARC .Voir la fonction CFBridgingRelease ici.

+ (NSString *)encodeUrlString:(NSString *)string {
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes
                         (kCFAllocatorDefault,
                          (__bridge CFStringRef)string,
                          NULL,
                          CFSTR("!*'();:@&=+$,/?%#[]"),
                          kCFStringEncodingUTF8)
                         );}
Neuneed
la source
2

Swift iOS:

Juste pour information: j'ai utilisé ceci:

extension String {

    func urlEncode() -> CFString {
        return CFURLCreateStringByAddingPercentEscapes(
            nil,
            self,
            nil,
            "!*'();:@&=+$,/?%#[]",
            CFStringBuiltInEncodings.UTF8.rawValue
        )
    }

}// end extension String
Vinod Joshi
la source
1
NSString *str = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                             NULL,
                             (CFStringRef)yourString, 
                             NULL, 
                             CFSTR("/:"), 
                             kCFStringEncodingUTF8);

Vous devrez vous libérer ou strvous autoriser .

Wevah
la source
1

Voici ce que j'utilise. Notez que vous devez utiliser la @autoreleasepoolfonctionnalité ou le programme pourrait planter ou bloquer l'EDI. J'ai dû redémarrer mon IDE trois fois jusqu'à ce que je réalise le correctif. Il semble que ce code soit conforme à l'ARC.

Cette question a été posée à plusieurs reprises et de nombreuses réponses ont été données, mais malheureusement toutes celles sélectionnées (et quelques autres suggérées) sont fausses.

Voici la chaîne de test que j'ai utilisée: This is my 123+ test & test2. Got it?!

Voici mes méthodes de classe Objective C ++:

static NSString * urlDecode(NSString *stringToDecode) {
    NSString *result = [stringToDecode stringByReplacingOccurrencesOfString:@"+" withString:@" "];
    result = [result stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    return result;
}

static NSString * urlEncode(NSString *stringToEncode) {
    @autoreleasepool {
        NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
                NULL,
                (CFStringRef)stringToEncode,
                NULL,
                (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
                kCFStringEncodingUTF8
            ));
        result = [result stringByReplacingOccurrencesOfString:@"%20" withString:@"+"];
        return result;
    }
}
Volomike
la source
0

Google l'implémente dans sa boîte à outils Google pour Mac . C'est donc un bon endroit pour savoir comment ils le font. Une autre option consiste à inclure la boîte à outils et à utiliser leur implémentation.

Découvrez la mise en œuvre ici . (Ce qui revient exactement à ce que les gens ont publié ici).

wrtsprt
la source
0

C'est ainsi que je fais cela rapidement.

extension String {
    func encodeURIComponent() -> String {
        return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
    }

    func decodeURIComponent() -> String {
        return self.componentsSeparatedByString("+").joinWithSeparator(" ").stringByRemovingPercentEncoding!
    }
}
Andy
la source
-1

// utilise la méthode d'instance NSString comme ceci:

+ (NSString *)encodeURIComponent:(NSString *)string
{
NSString *s = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}

+ (NSString *)decodeURIComponent:(NSString *)string
{
NSString *s = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}

rappelez-vous, vous ne devez encoder ou décoder que la valeur de votre paramètre, pas toutes les URL que vous demandez.

Lingtianlan
la source
2
stringByReplacingPercentEscapeusingencoding: seulement échappe & et = :-(
Sébastien Stormacq
1
Correct, donc les choses comme + ne sont pas encodées, quand elles doivent l'être. Alors n'utilisez pas la réponse ci-dessus
John Ballinger
-8
int strLength = 0;
NSString *urlStr = @"http://www";
NSLog(@" urlStr : %@", urlStr );
NSMutableString *mutableUrlStr = [urlStr mutableCopy];
NSLog(@" mutableUrlStr : %@", mutableUrlStr );
strLength = [mutableUrlStr length];
[mutableUrlStr replaceOccurrencesOfString:@":" withString:@"%3A" options:NSCaseInsensitiveSearch range:NSMakeRange(0, strLength)];
NSLog(@" mutableUrlStr : %@", mutableUrlStr );
strLength = [mutableUrlStr length];
[mutableUrlStr replaceOccurrencesOfString:@"/" withString:@"%2F" options:NSCaseInsensitiveSearch range:NSMakeRange(0, strLength)];
NSLog(@" mutableUrlStr : %@", mutableUrlStr );
ader
la source