8

UITextViewまたはUITextFieldのコンテンツをパラメーターとしてphpファイルに送信しようとしています

NSString *urlstr = [[NSString alloc] initWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@",nameField.text, tagsField.text, dreamEntry.text];

urlstrをログに記録するとき、UITextViewまたはUITextFieldにスペースが含まれていない限り、URL形式は問題ありません。スペースを%20に変換するにはどうすればよいですか?

編集

これが現在のコードです。クラッシュするだけでなく、URLを適切にエンコードしていません。

name = John Doe&tags = recurring nightmare&entry=テストテストテスト

に変換されます

name = John -1844684964oe&tags = recurringightmare&entry = Testing 4.214929e-307sting -1.992836e + 00sting

- (IBAction)sendButtonPressed:(id)sender
{

    NSString *urlString = [[NSString alloc] initWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@", nameField.text, tagsField.text, dreamEntry.text];

    NSString *encodedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    NSURL *url = [[NSURL alloc] initWithString:encodedString];

    NSLog(encodedString);

    NSLog(urlString);

    [urlString release];
    [url release];
    [encodedString release];


}
4

3 に答える 3

20

実際、これまでのすべての回答には少なくともいくつかの不正確さが含まれています。これは、TextFieldsでユーザーが提供したテキストの多くの一般的な値では、サーバーと正しく通信しません。

stringByAddingPercentEscapesUsingEncoding:パーセントは、有効なURL文字ではないすべての文字をエスケープします。このメソッドは、URL全体に1回適用する必要があります。

以前の回答stringByAddingPercentEscapesUsingEncoding:では、多くのスクリプト言語のURL構築クラスのように機能し、URL文字列全体に適用するべきではないと主張していますが、そうではありません。&エスケープされていないsとsの出力をチェックすることで、誰でも簡単にこれを確認できます?。したがって、文字列全体に適用することは問題ありませんが、「動的」URLコンテンツに適用するだけでは十分ではありません。

前の答えは、CGIクエリ文字列に含まれる名前と値に対してさらに作業を行う必要があるという点で正しいです。CGIはRFC3875で指定されているため、これはRFC3875パーセントエスケープと呼ばれることがよくあります。名前と値に、有効なURL文字であるが、URLの他の部分(、、、、、、、、、、、、、、、)で重要な文字が含まれてい;ないことを確認します。?:@&=$+{}<>,

ただし、文字列内のすべての文字が有効なURL文字であることを確認するために、文字列全体に対してプレーンなURLパーセントエスケープを実行して終了することも非常に重要です。あなたの例にはありませんが、一般的に、文字列の「静的」部分に有効なURL文字ではない文字が含まれている可能性があるため、それらもエスケープする必要があります。

残念ながら、NSStringRFC3875の重要な文字をエスケープする力はありません。そのため、そうするために深く掘り下げる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が含まれていると想像してください&。これはありそうもないことではありません。以前のソリューションでは、エスケープされていないアンパサンドがサーバーによってそのクエリ文字列ペアの値の部分を終了すると解釈されるため、サーバーがそのテキストを取得するまでに、その文字に続くすべてのテキストが失われます。

于 2010-11-10T00:34:27.683 に答える
14

文字列全体をURLエスケープするのではなく、動的コンポーネントをURLエスケープする必要があります。試す

NSString *urlStr = [NSString stringWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@",
                        [nameField.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                        [tagsField.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                        [dreamEntry.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                        nil];
NSURL *url = [NSURL URLWithString:urlStr];

コードの2番目の問題(そして間違いなく奇妙な印刷の理由)は、文字列を直接NSLogに渡すため、フォーマット文字列として扱われることです。あなたが使用する必要があります

NSLog(@"%@", encodedString);

代わりは。これにより、期待どおりに印刷されます。

編集:コードの3番目の問題は、自動解放されたオブジェクトと所有されているオブジェクトを混合し、最後にそれらをすべて解放することです。作成した3つのオブジェクトを確認し、後でリリースします。そのうちの1つは、alloc、copy、またはnewという単語で始まらない方法で作成されたため、後でリリースしないでください。問題のオブジェクトを特定することは、読者に任された演習です。

于 2009-05-27T19:41:31.477 に答える
0

あなたはあなたのURLを取り、使用することができます:

NSString *urlStr = [[NSString alloc] initWithFormat:@"http://server.com/file.php?name=%@&tags=%@&entry=%@",nameField.text, tagsField.text, dreamEntry.text];

NSString *encStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
于 2009-05-27T18:59:02.157 に答える