実際、これまでのすべての回答には少なくともいくつかの不正確さが含まれています。これは、TextFieldsでユーザーが提供したテキストの多くの一般的な値では、サーバーと正しく通信しません。
stringByAddingPercentEscapesUsingEncoding:
パーセントは、有効なURL文字ではないすべての文字をエスケープします。このメソッドは、URL全体に1回適用する必要があります。
以前の回答stringByAddingPercentEscapesUsingEncoding:
では、多くのスクリプト言語のURL構築クラスのように機能し、URL文字列全体に適用するべきではないと主張していますが、そうではありません。&
エスケープされていないsとsの出力をチェックすることで、誰でも簡単にこれを確認できます?
。したがって、文字列全体に適用することは問題ありませんが、「動的」URLコンテンツに適用するだけでは十分ではありません。
前の答えは、CGIクエリ文字列に含まれる名前と値に対してさらに作業を行う必要があるという点で正しいです。CGIはRFC3875で指定されているため、これはRFC3875パーセントエスケープと呼ばれることがよくあります。名前と値に、有効なURL文字であるが、URLの他の部分(、、、、、、、、、、、、、、、)で重要な文字が含まれてい;
ないことを確認します。?
:
@
&
=
$
+
{
}
<
>
,
ただし、文字列内のすべての文字が有効なURL文字であることを確認するために、文字列全体に対してプレーンなURLパーセントエスケープを実行して終了することも非常に重要です。あなたの例にはありませんが、一般的に、文字列の「静的」部分に有効なURL文字ではない文字が含まれている可能性があるため、それらもエスケープする必要があります。
残念ながら、NSString
RFC3875の重要な文字をエスケープする力はありません。そのため、そうするために深く掘り下げるCFString
必要があります。明らかに使用するCFString
のは苦痛なので、私は一般的に次のようにに追加しCategory
ますNSString
:
@interface NSString (RFC3875)
- (NSString *)stringByAddingRFC3875PercentEscapesUsingEncoding:(NSStringEncoding)encoding;
@end
@implementation NSString (RFC3875)
- (NSString *)stringByAddingRFC3875PercentEscapesUsingEncoding:(NSStringEncoding)encoding {
CFStringEncoding cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding);
NSString *rfcEscaped = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@";/?:@&=$+{}<>,",
cfEncoding);
return [rfcEscaped autorelease];
}
@end
これCategory
が適切に行われると、元の問題は次のように正しく解決できます。
NSString *urlEscapedBase = [@"http://server.com/file.php" stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding];
NSString *rfcEscapedName = [nameField.text stringByAddingRFC3875PercentEscapesUsingEncoding:
NSUTF8StringEncoding];
NSString *rfcEscapedTags = [tagsField.text stringByAddingRFC3875PercentEscapesUsingEncoding:
NSUTF8StringEncoding];
NSString *rfcEscapedEntry = [dreamEntry.text stringByAddingRFC3875PercentEscapesUsingEncoding:
NSUTF8StringEncoding];
NSString *urlStr = [NSString stringWithFormat:@"%@?name=%@&tags=%@&entry=%@",
urlEscapedBase,
rfcEscapedName,
rfcEscapedTags,
rfcEscapedEntry];
NSURL *url = [NSURL URLWithString:urlStr];
これは少し可変ですが、もっと明確になります。また、に提供されている変数リストは終了しstringWithFormat:
ないでくださいnil
。フォーマット文字列は、それに続く必要がある変数の正確な数を記述します。また、技術的には、クエリ文字列名(name、tags、entry、..)の文字列stringByAddingPercentEscapesUsingEncoding:
は当然のことながら実行する必要がありますが、この小さな例では、無効なURL文字が含まれていないことが簡単にわかります。
以前の解決策が正しくない理由を確認するために、のユーザー入力テキストにdreamEntry.text
が含まれていると想像してください&
。これはありそうもないことではありません。以前のソリューションでは、エスケープされていないアンパサンドがサーバーによってそのクエリ文字列ペアの値の部分を終了すると解釈されるため、サーバーがそのテキストを取得するまでに、その文字に続くすべてのテキストが失われます。