Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot load a NSURL with spaces or hashtags in iPhone app

Twitter has a nice feature that allows you to preload status messages using the following format:

http://twitter.com/?status=@HelloWorld Hello World

or alternatively:

http://twitter.com/?status=%40HelloWorld%20Hello%20World

I am trying to add a button to my iPhone app which will open Safari to the above pre-populated tweet.

However I am running into the problem where the percentage signs are being double escaped.

Here is the code that I have tried:

First an example of what does work

NSString* urlText = @"http://www.twitter.com/home?status=@HelloWorld";
NSURL *url = [NSURL URLWithString: urlText];
if (![[UIApplication sharedApplication] openURL:(NSURL*)url])
        NSLog(@"%@%@",@"Failed to open url:",[url description]);

This code works like a charm and outputs:

http://twitter.com/?status=%40HelloWorld

Code that doesn't work

NSString* urlText = @"http://www.twitter.com/home?status=@HelloWorld Hello World";
NSURL *url = [NSURL URLWithString: urlText];
if (![[UIApplication sharedApplication] openURL:(NSURL*)url])
        NSLog(@"%@%@",@"Failed to open url:",[url description]);

This creates a null NSURL. This I can only assume because URLWithString does not accept text with spaces in it.

So I tried this code:

NSString* urlText = @"http://www.twitter.com/home?status=@HelloWorld%20Hello%20World";
NSURL *url = [NSURL URLWithString: urlText];
if (![[UIApplication sharedApplication] openURL:(NSURL*)url])
   NSLog(@"%@%@",@"Failed to open url:",[url description]);

However that creates the URL:

http://twitter.com/?status=%40HelloWorld%2520Hello%2520World

So I have escaped my percentage sign %, which is of course not what I intended.

Of course people have been talking about using the function: stringByAddingPercentEscapesUsingEncoding

So I wrote this code:

NSString* urlText = @"http://www.twitter.com/home?status=@HelloWorld%20Hello%20World";
urlText = [urlText stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

NSURL *url = [NSURL URLWithString: urlText];
if (![[UIApplication sharedApplication] openURL:(NSURL*)url])
    NSLog(@"%@%@",@"Failed to open url:",[url description]);

However you again get the double escaping problem:

http://twitter.com/?status=%40HelloWorld%2520Hello%2520World

I'm hoping that someone might know some sort of work around. Ideally I would like to also include hashtags, but for now just getting spaces in would be a huge step forward.

like image 330
Alex Avatar asked Apr 06 '11 02:04

Alex


3 Answers

So it turns out that the problem wasn't being caused by the NSURL object but twitter itself.

This is the correct code to use:

NSString* urlText = @"http://twitter.com/home?status=@HelloWorld Hello World";
urlText = [urlText stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

NSURL *url = [NSURL URLWithString: urlText];
if (![[UIApplication sharedApplication] openURL:(NSURL*)url])
    NSLog(@"%@%@",@"Failed to open url:",[url description]);

One thing I didn't realize about twitter is this using this twitter address:

http://www.twitter.com/home?status=

will auto-escape your status.

While:

http://twitter.com/home?status=

will not auto-escape.

like image 187
Alex Avatar answered Sep 23 '22 04:09

Alex


Try this:

    NSString* urlText = @"http://www.twitter.com/home?status=@HelloWorld Hello World";  
    NSString* newText = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,(CFStringRef)urlText,NULL,(CFStringRef)@"!*'();:@&=+$,/?%#[]",kCFStringEncodingUTF8);
    NSURL* url = [NSURL URLWithString: urlText];
    if (![[UIApplication sharedApplication] openURL:(NSURL*)url])
    NSLog(@"%@%@",@"Failed to open url:",[url description]);
like image 1
0x8badf00d Avatar answered Sep 23 '22 04:09

0x8badf00d


I created this category on NSString for encoding strings as URLs:

@interface NSString (URLEncoding)
@property (readonly) NSString *URLEncodedString;
@end

@implementation NSString (URLEncoding)
- (NSString*)URLEncodedString
{
    NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8);
    return [result autorelease];
}
@end

In your case, you would use it like this:

NSString *urlText = @"http://www.twitter.com/home?status=@HelloWorld Hello World";
NSURL *url = [NSURL URLWithString:[urlText URLEncodedString]];
like image 1
indragie Avatar answered Sep 22 '22 04:09

indragie