web-dev-qa-db-fra.com

Objective-C et Swift codage d’URL

J'ai un NSString comme ceci:

http://www.

mais je veux le transformer en:

http%3A%2F%2Fwww.

Comment puis-je faire ceci?

134
Usi Usi

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éer un jeu de caractères combinant tout ce qui précède:

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

Créer une base64

Dans le cas du 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: stringByAddingPercentEncodingWithAllowedCharacters encodera également les caractères UTF-8 nécessitant un encodage.

Pré iOS7 utiliser Core Foundation
Utilisation 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: -stringByAddingPercentEscapesUsingEncoding ne produira pas le bon codage, dans ce cas, il ne codera rien qui retourne la même chaîne.

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding _ code 14 caractères:

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

testString:

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

encodedString:

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

Remarque: déterminez si cet ensemble de caractères répond à vos besoins, sinon modifiez-les au besoin.

RFC 3986 caractères nécessitant un encodage (% ajouté puisqu'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 \"% -. <>\^ _ `{|} ~"

319
zaph

Cela s'appelle encodage d'URL . Plus ici .

-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
    return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
           (CFStringRef)self,
           NULL,
           (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
           CFStringConvertNSStringEncodingToEncoding(encoding));
}
22
larsacus

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

D'une certaine manière cette solution fonctionne "bien". Il gère les caractères chinois, diacritiques et pratiquement 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écierai vraiment. Fondamentalement, il a une explication sur la raison pour laquelle cette chaîne encodée décodera exactement comme elle le souhaite.

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

7
Anonymous White
 NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NUL,(CFStringRef)@"parameter",NULL,(CFStringRef)@"!*'();@&+$,/?%#[]~=_-.:",kCFStringEncodingUTF8 );

NSURL * url = [[NSURL alloc] initWithString:[@"address here" stringByAppendingFormat:@"?cid=%@",encodedString, nil]];
4
Zahi

Cela peut fonctionner dans Objective C ARC.Use CFBridgingRelease pour transtyper un objet de type Core Foundation en tant qu’objet Objective-C et transférer la propriété de l’objet vers ARC. Voir Fonction CFBridgingRelease ici.

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

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
2
Vinod Joshi
NSString *str = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                             NULL,
                             (CFStringRef)yourString, 
                             NULL, 
                             CFSTR("/:"), 
                             kCFStringEncodingUTF8);

Vous devrez relâcher ou autorelease str vous-même.

1
Wevah

Google implémente cela dans leur Google Toolbox for Mac . C’est donc un bon endroit pour faire la meilleure chose au monde. Une autre option consiste à inclure la Boîte à outils et à utiliser leur implémentation.

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

0
wrtsprt

C'est comme ça que je fais ça à Swift.

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

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

Voici ce que j'utilise. Notez que vous devez utiliser le @autoreleasepool fonctionnalité ou le programme peut planter ou verrouiller l'IDE. 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 à maintes reprises et de nombreuses réponses ont été données, mais malheureusement, toutes les personnes sélectionnées (et quelques autres suggérées) ont tort.

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;
    }
}
0
Volomike