将UITextView/UITextField中的空格编码为URL格式

bcs*_*tos 8 iphone urlencode nsstring uitextfield uitextview

我正在尝试将UITextView或UITextField的内容作为参数发送到php文件

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

当我记录urlstr时,只要UITextView或UITextField不包含空格,url格式就可以了.我如何将空间转换为%20?

编辑

这是目前的代码,它不仅崩溃,而且没有正确编码url.

name = John Doe&tags =经常出现的梦魇和入口=测试测试测试

转换为

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


}
Run Code Online (Sandbox Code Playgroud)

bar*_*ton 20

实际上,以前的所有答案都包含至少一些不准确之处,对于TextFields中用户提供的文本的许多常见值,这些不准确都无法与服务器正确通信

stringByAddingPercentEscapesUsingEncoding:%转义所有不是有效URL字符的字符.此方法应对整个URL应用一次.

之前的回答声称其stringByAddingPercentEscapesUsingEncoding:工作原理类似于许多脚本语言中的URL构建类,您不应将其应用于整个URL字符串,但事实并非如此.任何人都可以通过检查未输出的&s和?s的输出来轻松验证这一点.因此可以应用于整个字符串,但仅适用于"动态"网址内容是不够的.

前面的答案是正确的,你必须对进入CGI查询字符串的名称和值做更多的工作.由于CGI由RFC3875指定,因此通常称为RFC3875%转义.它确保您的名字和值不包含有效URL字符,但它是在URL中的其他部分显著字符(;,?,:,@,&,=,$,+,{,},<,>,和,)

但是,通过对完整字符串执行普通URL百分比转义来确保字符串中的所有字符都是有效的URL字符,这一点非常重要.虽然您没有在您的示例中,但一般情况下,字符串的"静态"部分中可能存在不是有效URL字符的字符,因此您也需要转义它们.

不幸的是,NSString并没有给我们逃脱RFC3875重要角色的能力,所以我们不得不深入研究CFString这样做.显然,使用CFString是一种痛苦,所以我通常添加CategoryNSString像这样:

@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
Run Code Online (Sandbox Code Playgroud)

有了这个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];
Run Code Online (Sandbox Code Playgroud)

这是一个小变量重,只是更清楚.另请注意,提供给的变量列表stringWithFormat:不应nil终止.格式字符串描述了应遵循的变量的精确数量.此外,从技术上讲,查询字符串名称(名称,标签,条目,...)的字符串应该是stringByAddingPercentEscapesUsingEncoding:理所当然的,但在这个小例子中,我们可以很容易地看到它们不包含无效的URL字符.

要查看以前的解决方案为何不正确,请假设用户输入的文本dreamEntry.text包含一个&,这不是不可能的.使用先前的解决方案,在服务器获得该文本时,该字符后面的所有文本都将丢失,因为未转义的&符号将被服务器解释为结束该查询字符串对的值部分.


Lil*_*ard 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];
Run Code Online (Sandbox Code Playgroud)

您的代码的第二个问题(毫无疑问是奇数打印的原因)是您将字符串直接传递给NSLog,因此它被视为格式字符串.你需要使用

NSLog(@"%@", encodedString);
Run Code Online (Sandbox Code Playgroud)

代替.这将使其按预期打印.

编辑:您的代码的第三个问题是您正在混合自动释放和拥有的对象,然后在最后释放它们.去看看你创建的3个对象,以及随后发布的对象.其中一个不应该在以后发布,因为它是由一个不以"alloc","copy"或"new"开头的方法生成的.识别有问题的对象是留给读者的练习.