NSURL URLWithString:relativeToURL: is clipping relative url - ios

I'm trying to implement an iOS app, which uses RestKit. In all examples I've seen so far the following code is used to create the URLs:
NSURL *baseURL = [NSURL URLWithString:#"https://api.service.com/v1"];
NSURL *relativeURL = [NSURL URLWithString:#"/files/search" relativeToURL:baseURL];
But then [relativeURL absoluteString] will return https://api.service.com/files/search.
So I tried a few examples:
NSURL *baseURL1 = [NSURL URLWithString:#"https://api.service.com/v1/"];
NSURL *baseURL2 = [NSURL URLWithString:#"https://api.service.com/v1"];
NSURL *baseURL3 = [NSURL URLWithString:#"/v1" relativeToURL:[NSURL URLWithString:#"https://api.service.com"]];
NSURL *relativeURL1 = [NSURL URLWithString:#"/files/search" relativeToURL:baseURL1];
NSURL *relativeURL2 = [NSURL URLWithString:#"/files/search" relativeToURL:baseURL2];
NSURL *relativeURL3 = [NSURL URLWithString:#"/files/search" relativeToURL:baseURL3];
NSURL *relativeURL4 = [NSURL URLWithString:#"files/search" relativeToURL:baseURL1];
NSURL *relativeURL5 = [NSURL URLWithString:#"files/search" relativeToURL:baseURL2];
NSURL *relativeURL6 = [NSURL URLWithString:#"files/search" relativeToURL:baseURL3];
NSLog(#"1: %#", [relativeURL1 absoluteString]);
NSLog(#"2: %#", [relativeURL2 absoluteString]);
NSLog(#"3: %#", [relativeURL3 absoluteString]);
NSLog(#"4: %#", [relativeURL4 absoluteString]);
NSLog(#"5: %#", [relativeURL5 absoluteString]);
NSLog(#"6: %#", [relativeURL6 absoluteString]);
And this is the output:
1: https://api.service.com/files/search
2: https://api.service.com/files/search
3: https://api.service.com/files/search
4: https://api.service.com/v1/files/search
5: https://api.service.com/files/search
6: https://api.service.com/files/search
So the only example returning what I want is #4. Can anyone explain why?

I read [RFC1808] which defines the normative algorithm for resolving relative URLs
2 issues:
the relative url may not start with a / or it is considered to be absolute:
Step 4: If the embedded URL path is preceded by a slash "/", the
path is not relative and we skip to Step 7."
when the base url ends with a non-slash. everything from the last slash on is skipped
Step 6: The last segment of the base URL's path (anything
following the rightmost slash "/", or the entire path if no
slash is present) is removed and the embedded URL's path is
appended in its place. The following operations are
then applied, in order, to the new path:"
so that explains it. the baseURL needs to end in a / and the relative url shouldn't start with a /

You have two problems here:
Firstly, the string /files/search is an absolute path since it starts with a slash. Resolving it against any existing URL will ignore the existing path.
Secondly, https://api.service.com/v1 does not have a trailing slash to indicate it's a directory. Any strings resolved against it will always ignore the v1 portion.
To conclude, you need that combo of a relative path — files/search — and directory base URL — https://api.service.com/v1/.

Another example:
//it's right
NSURL *url = [NSURL URLWithString:#"getValidNumber" relativeToURL:[NSURL URLWithString:#"http://dns.test.com:22009/service/"]];
//error
NSURL *url = [NSURL URLWithString:#"getValidNumber" relativeToURL:[NSURL URLWithString:#"dns.test.com:22009/service/"]];
//error
NSURL *url = [NSURL URLWithString:#"/getValidNumber" relativeToURL:[NSURL URLWithString:#"http://dns.test.com:22009/service"]];
`
The 'http://' is necessary to use this method.

Related

NSURL URLWithString returns nil

I am stuck in a very obvious method of NSURL class URLWithString I am passing a string and while creating URL it returns nil, my string is perfect. When ever I uses same string in browser then it is working fine. I am using following method to convert NSString to NSURL:
NSURL *url = [NSURL URLWithString:urlString];
//urlString is my perfect string
I have also tried to encode my string first by using following
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
// using this line my output string when I log url is "url%10%10%10%10%10%10..."
%10 becomes the suffix of my url with around 100+ repetition.
If any one has idea what %10 is or what can be done to overcome this problem.
here is my urlString:
Use below code to resolve your problem.
NSString *str = msgDetail[#"thumbnail"];
NSString* webStringURL = [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
NSURL* url = [NSURL URLWithString:webStringURL];
yes what was wrong in my string were many unidentified characters due to copying from internet site, if anyone of the reader facing this issue can copy and paste your string as see the count. And confirm.
Thanks
Try below solution
NSURL *url = [NSURL URLWithString:[urlString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
Check it..!

Playing movie downloaded with FTP in iOS

I have an application that downloads movies from an ftp-server and then plays them with an MPMoviePlayerController. However the movieplayer fails with MPMovieFinishReasonPlaybackError.
the code looks like this:
NSURL *url = [NSURL fileURLWithPath:[contents objectAtIndex:index]];
NSLog(#"url: %#",url);
self.movieController = [[MPMoviePlayerController alloc] initWithContentURL:url];
the nslog gives this answer:
url: file://localhost/var/mobile/Applications/E8C9DFE8-9802-4EC1-B560-3EEE96E0AF5E/Documents/media/testfilm.mov
Does anybody have an idea on how to get the movie to play? If I add the movie to the project and use the following code the movie works.
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"testfilm" ofType:#"mov"]];
You are using fileURLWithPath: for a remote file, that is wrong.
Use URLWithString: for remote files instead.
See the reference on that exact subject - particularly the parameters section;
URLWithString:
Creates and returns an NSURL object initialized with a provided string.
+ (id)URLWithString:(NSString *)URLString
Parameters
URLString
The string with which to initialize the NSURL object. Must be a URL that conforms to RFC 2396. This method parses URLString according to RFCs 1738 and 1808. (To create NSURL objects for file system paths, use fileURLWithPath:isDirectory: instead.)
Return Value
An NSURL object initialized with URLString. If the string was malformed, returns nil.
Discussion
This method expects URLString to contain any necessary percent escape codes, which are ‘:’, ‘/’, ‘%’, ‘#’, ‘;’, and ‘#’. Note that ‘%’ escapes are translated via UTF-8.

IOS - How do I add segments to NSURL?

Suppose you have a URL that looks like http://localhost:5867 and your wanted to append '/something' to the url. How do I append segments to this URL?
I am trying this:
//_baseURL is NSURL* and documentid is NSString*
NSURL* url = [_baseURL URLByAppendingPathComponent:documentid];
Oddly.. xcode(4.6.2) will not output the resulting URL to console.
NSLog(#"%#", [url absoluteString]);//nothing output
Thanks!
Edit
I am working in a workspace. The code that I am debugging is a static lib which is in the workspace. Could this be the culprit of all this weirdness??
Fixed
I think the reason I was having problems was because my workspace was not configured correctly and I was actually executing an older version of my static lib. This explains why I wasn't getting NSLog'ing and why the result were unexpected. I found this post which helped me understand the workspace and how to configure it for a static library. Thanks a lot for everyone's time!
There is a class message,
+ (id)URLWithString:(NSString *)URLString relativeToURL:(NSURL *)baseURL
So,
NSURL *base = [NSURL URLWithString: #"http://localhost:5867"];
NSURL *child = [NSURL URLWithString: #"something" relativeToURL:base];
NSURL *base = [NSURL URLWithString:#"http://localhost:5867"];
NSURL *url = [base URLByAppendingPathComponent:#"something"];
NSLog(#"%#", [url absoluteString]);
This works for me and prints http://localhost:5867/something, so check your variables (maybe one of them is nil or an empty string?).

How does one append something like "?x=123" to an NSURL?

I have an NSURL of the form
"http://abc.def.com:1234/stuff/"
and I want to append to it so the final url is like this
"http://abc.def.com:1234/stuff/?x=123".
But if I do this
url = [NSURL URLWithString:#"http://abc.def.com:1234/stuff/?"];
url = [url URLByAppendingPathComponent:#"x=123"];
Then the result is
http://abc.def.com:1234/stuff/x=123?
(its the same result if URLByAppendingPathExtension is used).
But if I do this
url = [NSURL URLWithString:#"http://abc.def.com:1234/stuff/?"];
url = [url URLByAppendingPathComponent:#"x=123"];
Then the result is
http://abc.def.com:1234/stuff/%3Fx=123
(also the same result if URLByAppendingPathExtension is used).
Neither of which is what I am after. How do I get a final result of "http://abc.def.com:1234/stuff/?x=123" ?
I think the simplest answer here is to create a new URL using the old one as the base URL.
url = [NSURL URLWithString:#"?x=123" relativeToURL:url]
Here is a unit test that checks the logic
- (void)testCreatingQueryURLfromBaseURL
{
NSURL *url = [NSURL URLWithString:#"http://foo.com/bar/baz"];
url = [NSURL URLWithString:#"?x=1&y=2&z=3" relativeToURL:url];
STAssertEqualObjects([url absoluteString], #"http://foo.com/bar/baz?x=1&y=2&z=3", nil);
}
Create your actual NSURL object last, from an NSString that you build up as needed:
NSString *urlString = #"http://www.site.com/";
if (some condition)
urlString = [urlString stringByAppendingString:#"?x=123"];
NSURL *url = [NSURL URLWithString:urlString];

NSURL URLWithString the url is always nil

My code is like this :
NSString *urlStr = [NSString stringWithFormat:#"https://xxx.xxx.xx.xx/Pages/Service/FMService.svc/FileAudit?user=%#&pass=%#&fileId=%d&isAudited=1&opinion=%#",appDelegate.user.userName,appDelegate.user.password,self.todo.fileId,self.opinion];
NSLog(#"URL=%#",urlStr);
NSURL *url = [NSURL URLWithString:urlStr];
And the url = (NSURL *) 0*00000000#"< nil >"
how can I work it out? thank you in advance!
For debugging purposes, I would build up urlStr piece by piece instead of combining five NSStrings all at once. Put in an NSLog(#"%#", urlStr) statement after each addition to urlStr. This will reveal which piece of the puzzle is causing the problem.

Resources