需要为URL编码NSString。 CFURLCreateStringByAddingPercentEscapes破坏我的字符串

时间:2012-09-11 14:36:28

标签: ios cocoa-touch rest nsstring urlencode

我的音乐播放器应用需要能够通过REST API将歌曲,艺术家和专辑名称发送到Last.fm。为了正确地发布这些值,我需要对它们进行编码,以便它们是URL安全的(替换&,/,+等)

我做了很多研究,但我找不到适合我的答案。我在网上和StackOverflow上找到的最常见的答案是:

NSString * encodedString = (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,(__bridge CFStringRef)stringToEncode,NULL,(CFStringRef)@"!*'();:@&=+$,/?%#[]",kCFStringEncodingUTF8 );

但是,结果似乎不是我所期望的。来自NSLog的示例显示了之前和之后的结果:

艺术家

2012-09-11 10:20:27.803 albums[7647:5c03] Depeche Mode
2012-09-11 10:20:27.804 albums[7647:5c03] Depeche2ode

歌曲

2012-09-11 10:20:27.807 albums[7647:5c03] I Want It All (Album Version)
2012-09-11 10:20:27.808 albums[7647:5c03] I2ant2t-0X1.1A1A10D39EP-485ll228Album2ersion2

相册

2012-09-11 10:20:27.810 albums[7647:5c03] Playing The Angel
2012-09-11 10:20:27.811 albums[7647:5c03] Playing2he-0X1.1A1A10D39EP-485ngel

不是仅仅使用转义码替换保留的字符,而是纠缠我的字符串。

我已经尝试过这样做的NSString方法,我也得到了同样的结果:

NSString *encodedString = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

艺术家

2012-09-11 10:29:53.780 albums[7675:5503] Depeche Mode
2012-09-11 10:29:53.787 albums[7675:5503] Depeche2ode

歌曲

2012-09-11 10:29:53.789 albums[7675:5503] I Want It All (Album Version)
2012-09-11 10:29:53.790 albums[7675:5503] I2ant2t-0X1.1A1A100A78P-485ll2Album2ersion)

相册

2012-09-11 10:29:53.792 albums[7675:5503] Playing The Angel
2012-09-11 10:29:53.793 albums[7675:5503] Playing2he-0X1.1A1A100A78P-485ngel

我进行了广泛的搜索,发现没有出现完全相同的问题。上面列出的解决方案(建议在几十个博客和SO帖子上)似乎适用于其他人。

我真的不懂字符串编码。我从来没有在另一个平台上处理它,所以我不能告诉你我用扩展码代替的字符串是如何被编码的。我可以告诉你,我是从MPMediaItem方法valueForKey:MPMediaItemPropertyTitle得到它的,所以不管它是什么,Apple正在回归。从NSLogged或UI中查找从该外观返回的字符串。

1 个答案:

答案 0 :(得分:2)

您的字符串显示不正确的原因很可能是因为您将URL作为第一个参数传递给NSLog,该参数接受第一个参数的格式字符串。任何百分比字符都将被解释为格式字符串指令。

您需要像这样记录您的网址:

NSLog(@"%@", urlToLog);

此外,代码中最左侧的__bridge不正确。 CFURLCreateStringByAddingPercentEscapes名称中包含“Create”,表示返回的字符串需要释放。我们想告诉ARC为我们处理这个问题,因此我们应该使用__bridge_transfer 所有权转移到ARC:

NSString * encodedString = (__bridge_transfer NSString *)CFURLCreateString...