Objective-CおよびSwift URLエンコーディング


137

私はNSStringこのようなものがあります:

http://www.

しかし、私はそれを次のように変換したい:

http%3A%2F%2Fwww.

これどうやってするの?


1
ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~以下のような暗号化された文字列を持っています-以下の解決策のどれもこれに対処していないようです!
Mahendra Liya 2013年

回答:


324

必要な文字をエスケープすることはもう少し仕事です。

コード例

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より前のバージョンでは、
ARCでCore Foundation を使用して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"  

encryptedString:

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

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

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

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

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

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


1
また、NSStringの-stringByAddingPercentEscapesUsingEncodingメソッドを使用できることに注意してください。
マイクウェラー

2
ああ、はい、今はファンキーなstringByAddingPercentEscapesUsingEncoding行動を覚えています。「&」と「=」、またはそのようなとんでもないものだけをエンコードします。
マイクウェラー

2
RFC1738によると、追加の文字もエンコードする必要があります。したがって、これはOPの質問に答えますが、汎用URLエンコーダーとしての有用性は限られています。たとえば、ドイツ語のウムラウトなどの非英数字は処理しません。
Alex Nauda 2013

3
これは機能しません(iOS 7の場合)。これは&を%26に変換しません。
coolcool1994 2014

1
NSStringwith から必要な文字セットを作成し、characterSetWithCharactersInStringwith invertedSetを逆にしてwith で使用しstringByAddingPercentEncodingWithAllowedCharactersます。例については、このSOの回答を参照してください。
zaph

22

これはURLエンコーディングと呼ばれます。詳細はこちら

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

3
これは、投稿したリンクのコンテンツが回答に含まれている場合に、はるかに役立ちます。
chownコマンド

1
CFURLCreateStringByAddingPercentEscapes()廃止予定です。[NSString stringByAddingPercentEncodingWithAllowedCharacters:]代わりに使用してください。
2017年

7

これは私の解決策ではありません。他の誰かがスタックオーバーフローで書いたが、私はその方法を忘れてしまった。

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

- (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でスペースを表すのが好きです。それで全部です。



[self UTF8String]とは何ですか?
Yuchao Zhou

1
@yuchaozhこれは、NSStringのカテゴリ内に配置する関数です。つまり、selfはNSStirngであり、[self UTF8String]は、おそらく、その文字列をUTF8形式で返します。
ケルシー

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

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

1
エンコードされた文字列とURLを解放します。このコードはエンコードパラメータに関するものです。「パラメータ」の代わりにアドレス全体のパス文字列をエンコードします。
Zahi

これは私にとってはうまくいきました...私が問題を抱えていた&文字もエンコードしました。
ВикторИванов

3

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

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

2

Swift iOS:

参考情報:私はこれを使用しました:

extension String {

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

}// end extension String

1
NSString *str = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                             NULL,
                             (CFStringRef)yourString, 
                             NULL, 
                             CFSTR("/:"), 
                             kCFStringEncodingUTF8);

str自分で解放または自動解放する必要があります。


1

これが私が使うものです。あなたが使用しなければならないことに注意してください@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

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

ここで実装を確認してください。(これは、人々がここに投稿したものに正確に帰着します)。


0

これは私が迅速にこれを行う方法です。

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

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

-1

//次のようにNSStringインスタンスメソッドを使用します:

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

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

要求するすべてのURLではなく、パラメータ値のエンコードまたはデコードのみを行う必要があることを覚えておいてください。


2
stringByReplacingPercentEscapeusingencoding:&および= :-(のみエスケープします
–SébastienStormacq

1
正しいので、+のようなものがエンコードされる必要はありません。したがって、上記の回答は使用しないでください
John Ballinger、2013年

-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 );
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.