web-dev-qa-db-ja.com

Objective-CおよびSwift URLエンコード

次のようなNSStringがあります。

http://www.

しかし、私はそれをに変換したい:

http%3A%2F%2Fwww.

これどうやってするの?

134
Usi Usi

必要な文字をエスケープするには、もう少し手間がかかります。

サンプルコード

iOS7以降:

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

NSLog出力:

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

以下は、便利なURLエンコード文字セットです。

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

上記のすべてを組み合わせた文字セットを作成します。

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

Base64の作成

Base64文字セットの場合:

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

Swift 3.0の場合:

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

Swift 2.xの場合:

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

注:stringByAddingPercentEncodingWithAllowedCharactersは、エンコードが必要なUTF-8文字もエンコードします。

IOS7以前はCore Foundationを使用
ARCでCore Foundationを使用する:

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

ARCなしでCore Foundationを使用する:

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

注:-stringByAddingPercentEscapesUsingEncodingは正しいエンコードを生成しません。この場合、同じ文字列を返すものはエンコードしません。

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncodingは14文字をエンコードします:

`#%^ {} [] | \" <> +エスケープされたパーセントとしてのスペース文字。

testString:

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

encodedString:

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

注:この文字セットがニーズに合っているかどうかを検討し、必要に応じて変更しないでください。

エンコードが必要なRFC 3986文字(エンコードプレフィックス文字であるため、%が追加されます):

「!#$& '()* +、/:; =?@ []%」

一部の「予約されていない文字」はさらにエンコードされます。

"\ n\r \"%-。<>\^ _ `{|}〜"

319
zaph

RL encoding と呼ばれます。もっと こちら

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

これは私の解決策ではありません。他の誰かがstackoverflowで書いたが、私はその方法を忘れてしまった。

どういうわけか、このソリューションは「うまく」機能します。発音区別記号、漢字、その他ほとんどすべてを処理します。

- (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;
}

誰かがこのコードを書いた人を教えてくれたら、本当に感謝しています。基本的に、彼はこのエンコードされた文字列が希望どおりに正確にデコードされる理由を説明しています。

私は彼のソリューションを少し修正しました。スペースを+ではなく%20で表すのが好きです。それで全部です。

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

これは、Objective C ARCで機能します。CFBridgingReleaseを使用して、Core FoundationスタイルのオブジェクトをObjective-Cオブジェクトとしてキャストし、オブジェクトの所有権をARCに転送します。 Function CFBridgingRelease hereを参照してください。

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

Swift iOS:

情報提供のみ:これを使用しました:

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);

strを自分でリリースまたは自動リリースする必要があります。

1
Wevah

Googleは、これを Mac用Googleツールボックス で実装しています。だから、彼らはそれをやっている方法をピークにするのに良い場所です。別のオプションは、ツールボックスを含めて実装を使用することです。

実装をチェックアウトします こちら 。 (これは、人々がここに投稿したものに正確になります)。

0
wrtsprt

これは私がスウィフトでこれをやっている方法です。

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

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

ここに私が使用するものがあります。 @autoreleasepool機能を使用する必要があることに注意してください。そうしないと、プログラムがクラッシュしたり、IDEがロックアップする可能性があります。修正が実現するまで、IDEを3回再起動する必要がありました。このコードはARCに準拠しているようです。

この質問は何度も聞かれ、多くの答えが出されましたが、悲しいことに、選択されたすべて(および他のいくつかの提案)が間違っています。

私が使用したテスト文字列は次のとおりです。This is my 123+ test & test2. Got it?!

これらは私の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