NSURL baseURL returns nil. Any other way to get the actual base URL
Asked Answered
F

6

12

I think I don't understand the concept of "baseURL". This:

NSLog(@"BASE URL: %@ %@", [NSURL URLWithString:@"http://www.google.es"], [[NSURL URLWithString:@"http://www.google.es"] baseURL]);

Prints this:

BASE URL: http://www.google.es (null)

And of course, in the Apple docs I read this:

Return Value The base URL of the receiver. If the receiver is an absolute URL, returns nil.

I'd like to get from this example URL:

https://www.google.es/search?q=uiviewcontroller&aq=f&oq=uiviewcontroller&sourceid=chrome&ie=UTF-8

This base URL

https://www.google.es

My question is simple. Is there any cleaner way of getting the actual base URL without concatenating the scheme and the hostname? I mean, what's the purpose of base URL then?

Filum answered 9/4, 2013 at 7:20 Comment(2)
What result, exactly, are you looking for?Terce
Sorry, I forgot to mention that: I want from this URL for example: google.es/… to get the "base URL" part -> google.esFilum
M
31

-baseURL is a concept purely of NSURL/CFURL rather than URLs in general. If you did this:

[NSURL URLWithString:@"search?q=uiviewcontroller"
       relativeToURL:[NSURL URLWithString:@"https://www.google.es/"]];

then baseURL would be https://www.google.es/. In short, baseURL is only populated if the NSURL is created using a method that explicitly passes in a base URL. The main purpose of this feature is to handle relative URL strings such as might be found in the source of a typical web page.

What you're after instead, is to take an arbitrary URL and strip it back to just the host portion. The easiest way I know to do this is a little cunning:

NSURL *aURL =  [NSURL URLWithString:@"https://www.google.es/search?q=uiviewcontroller"];
NSURL *hostURL = [[NSURL URLWithString:@"/" relativeToURL:aURL] absoluteURL];

This will give a hostURL of https://www.google.es/

I have such a method published as -[NSURL ks_hostURL] as part of KSFileUtilities (scroll down the readme to find it documented)

If you want purely the host and not anything like scheme/port etc. then -[NSURL host] is your method.

Mile answered 9/4, 2013 at 9:14 Comment(2)
Bottom line: "baseURL is only populated if the NSURL is created using a method that explicitly passes in a base URL". Thanks!Sheryllshetland
It's worth noting that in your example hostURL != [NSURL URLWithString: https://www.google.es/]. NSURL knows how they're constructed and doesn't consider them equivalent, even though their absolute URL are the same. I added a slightly modified version to my repo (sorry for the Swift): URL(string: "/", relativeTo: self).flatMap { URL(string: $0.absoluteString) }Implead
H
3

Docs for BaseURL.

baseURL
Returns the base URL of the receiver.

- (NSURL *)baseURL
Return Value
The base URL of the receiver. If the receiver is an absolute URL, returns nil.

Availability
Available in iOS 2.0 and later.
Declared In
NSURL.h

Seems it only works for relative URLs.

You could possibly use ...

NSArray *pathComponents = [url pathComponents]

and then take the bits you want.

Or try...

NSString *host = [url host];
Haviland answered 9/4, 2013 at 7:40 Comment(1)
The pathComponents will only decompose the path, so one can't take the baseURL from there (they can, but the strategy will be similar and more complex than using path simply). Also, host will omit the URL scheme (http:// for example)Buff
H
1

you can use host method

NSURL *url = [[NSURL alloc] initWithString:@"http://www.hello.com"];

NSLog(@"Host:%@", url.host);

result:

Host:www.hello.com
Heshvan answered 4/12, 2019 at 12:37 Comment(0)
B
0

It might be just me, but when I think further about the double-URL solution, it sounds like something that could stop working between OS updates. So I decided to share yet another solution, definitely not beautiful either, but I find it more readable by the general public since it doesn't rely on any hidden specificity of the framework.

if let path = URL(string: resourceURI)?.path {
  let baseURL = URL(string: resourceURI.replacingOccurrences(of: path, with: ""))
  ...
}
Buff answered 21/10, 2018 at 19:46 Comment(0)
T
0

I've managed to do it by using url.deletingLastPathComponent method in Swift

let baseUrl = url.deletingLastPathComponent()
Tutorial answered 5/7, 2023 at 17:36 Comment(2)
This doesn't give the desired result if there is more than one path component in the URL.Ilyse
It is true that in my case I have only one path component. I had struggles to find answer to this 🤔 Other solutions did not work for me :)Tutorial
D
-1

Here's a quick, easy, and safe way to fetch the base URL:

NSError *regexError = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"http://.*/" options:NSRegularExpressionCaseInsensitive error:&regexError];

if (regexError) {
    NSLog(@"regexError: %@", regexError);
    return nil;
}

NSTextCheckingResult *match = [regex firstMatchInString:url.absoluteString options:0 range:NSMakeRange(0, url.absoluteString.length)];

NSString *baseURL = [url.absoluteString substringWithRange:match.range];
Directed answered 16/12, 2013 at 18:13 Comment(1)
What about https and other schemes?Hue

© 2022 - 2025 — McMap. All rights reserved.