confused by substring result of stringByDeletingLastPathComponent - objective-c

my code
NSMutableString *s= (NSMutableString *)[#"http://www.yahoo.com/index.html" stringByDeletingLastPathComponent];
what I expected result of s is
http://www.yahoo.com
but the code above show s is:
http:/www.yahoo.com
Your comment welcome

You should use NSURL, not NSString:
NSURL *url = [[NSURL URLWithString:#"http://www.yahoo.com/index.html"] URLByDeletingLastPathComponent];
Yielding:
http://www.yahoo.com/
If you absolutely need a string from this, you can then do:
NSString *urlString = url.absoluteString;
Or, if you really needed a mutable string, don’t cast it to NSMutableString, but do create a mutable copy:
NSMutableString *urlString = [url.absoluteString mutableCopy];
But, in general, where possible, you should stay with NSURL when dealing with URLs. And when tempted to use file paths, use file URLs instead.

The annotation for this method is explained as follows。
Apple Document: Note that this method only works with the file paths (not, for example, the string representations of URLs).
But you string is clearly a full URL address, does not belong to the file path, so we will assemble them into a URL, using URL classification URLByDeletingLastPathComponent to intercept
NSString *urlString = #"http://www.yahoo.com/index.html";
NSURL* URL = [NSURL URLWithString: urlString];
NSURL* lastPathUrl = [URL URLByDeletingLastPathComponent];
NSString* lastPathString = lastPathUrl.absoluteString;
NSLog(#"---%#---", lastPathString);

Related

NSURL path not working, but NSString path working

I saved an object to file and I am now trying to run a check on whether or not that file exists. I have confirmed the path of the file and concluded that the IF statement works when I hard code the path as a NSString, see first block. However, when I try saving the path as a NSURL, and convert it to an NSString so that fileManager can run it's method on it, it does not locate the file at the path. Anything that I am missing here?
LOCATES FILE HERE USING HARD CODE NSSTRING:
[NSKeyedArchiver archiveRootObject:employees toFile:#"/Users/xxx/Documents/employees.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *employeesPath = #"/Users/xxx/Documents/employees.plist";
if ([fileManager fileExistsAtPath:employeesPath]) {
NSLog(#"It exists! yes!");
}
else {
NSLog(#"Doesn't exist, sorry bud");
}
DOES NOT LOCATE FILE USING NSURL:
[NSKeyedArchiver archiveRootObject:employees toFile:#"/Users/xxx/Documents/employees.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *employeesPath = [NSURL fileURLWithPath:#"/Users/xxx/Documents/employees.plist"];
NSString *employeesString = [employeesPath absoluteString];
if ([fileManager fileExistsAtPath:employeesString]) {
NSLog(#"It exists! yes!");
}
else {
NSLog(#"Doesn't exist, sorry bud");
}
EDIT
-- if I wanted to use the NSURL method, I could by making a function to store the path into a NSString the proper way. This ended up working:
NSString* getPropertyListPath() {
NSURL *documentDir = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
NSURL *plist = [documentDir URLByAppendingPathComponent:#"employees.plist"];
return plist.path;
}
You are correct to use NSURL, giuseppe, instead of string literals.
NSURL is more compatible and robust than a string literal. NSURL types will give you access to more methods and functionality.
The trick that you stumbled into is that you needed the file path without the "scheme" or "domain" included in the format.
You are correct to call the path method on your NSURL object to retrieve the correct path format for what you need. The path method only returns the path component to the NSURL address path. It doesn't return the scheme or domain components.
NSString *correctPathFormat = [yourNsurlObject path];
For Example:
If I have a file in the following directory path:
NSString* myDirPath = #"/Users/yourUserName/imageFolder";
and load this into a NSURL object:
NSURL *nsurlDirPath = [NSURL fileURLWithPath:myDirPath];
then append the file name and file type:
NSURL *nsurlFilePath = [nsurlDirPath URLByAppendingPathComponent:#"employee.plist"];
If you call the [nsurlFilePath absoluteString] method you will get an NSString value in the format of "scheme://domain/path"
NSString *retrievePath = [nsurlFilePath absoluteString];
NSLog(#"%#",retrievePath);
This logs out:
file:///Users/yourUserName/imageFolder/employee.plist
Special Note: This is the equivalent to the file path:
file://localhost/Users/yourUserName/imageFolder/employee.plist
The "localhost" is just omitted because this is by default implied, so that is why you see the tripple "///" in "file:///Users/...".
"localhost" is an alias that refers to the local device's ip address, or in other words, the device the code is running on.
Finally, to get the correct path format you need you would run the 'path' method on the NSURL object, which takes us back to the answer at the very beginning of my response:
NSString *correctPathFormat = [nsurlFilePath path];
This logs out the correct "path" component, minus the "scheme" & "domain":
/Users/yourUserName/imageFolder/employee.plist
Further Explanation:
NSURLS have three parts:
scheme : [http, https, ftp, file]
domain : [www.stackoverflow.com, localhost, ipAddress]
path : [/questions/26663573/, /Users/youUserName/subDirName]
scheme | domain | path
file://localhost/Users/youruserName/file.txt
Don't use a NSURL as a file path intermediary.
NSURL *employeesPath = [NSURL fileURLWithPath:#"/Users/xxx/Documents/employees.plist"];
NSString *employeesString = [employeesPath absoluteString];
NSLog(#"employeesString: %#", 'employeesString');
Output:
employeesString: 'file:///Users/xxx/Documents/employees.plist'
Which is clearly not a file path.

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

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?
-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.
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];
you can use host method
NSURL *url = [[NSURL alloc] initWithString:#"http://www.hello.com"];
NSLog(#"Host:%#", url.host);
result:
Host:www.hello.com
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: ""))
...
}
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];

How can I append a hashtag to local html file URL obtained with fileURLWithPath?

I am trying to build a URL string that will be passed to UIWebView object. Up until now I have been pointing to remote files and have now moved the files into the main bundle.
I imported my files using the "create folder reference" option and want to point to the index.html file inside of a folder named 'html'.
I need to append hashtags to the URL generated by the code below but keep getting this error:
-[NSURL stringByAppendingString:]: unrecognized selector sent to instance
I can't figure out why when casting my variables as a NSString I am receiving this error when trying to append to it.
Here is my code:
NSInteger rowNumber = indexPath.row;
NSInteger metroRank = rowNumber+1; //sorted by rank, adding one because of zero-based array
NSString *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html" inDirectory:#"html"]];
NSString *urlSuffix = [NSString stringWithFormat:#"#pg=metro&view=%d", metroRank];
NSString *metroViewURL = [url stringByAppendingString:urlSuffix];
When the above code hits 'stringByAppendString' that is when I receive the error.
Convert it to a NSString first:
NSString *newURL = [[oldURL absoluteString] stringByAppendingString:#"#myhashtag"];
[NSURL fileURLWithPath:] does not return a NSString, but a NSURL. NSURL does not implement the stringByAppendingString selector. You can use URLByAppendingPathComponent: instead.

Declare an NSString With Format Specifiers and use it as a URL to open in UIWebview

I have an int containing a number. I am wanting to declare an NSString so I can use use format specifiers when assigning a value to it.
I thought it might be something like this:
NSString[NSString stringWithFormat] myString;
myString = [#"http://myurl.com/%d",myInt];
I gather this is not the case, so question one is: How do I declare an NSString that can handle format specifiers and then assign it a value using format specifiers? The purpose of this NSString is to hold a URL, exactly like the second line above.
Question two is, How do I then use this string as a URL to open in a UIWebView?
I assume I use something like this:
[webView loadRequest:
Sadly, this is as far as my knowledge stretches. Is there a way I can tell my UIWebView (webView above) to use the NSString with the URL I mentioned earlier?
I intend on having the NSString as a global variable, as it will be assigned it's value inside a C function. And 'webView' will use it inside a (what I think is a) method. All of this code is in the same file, the Delegate.m file. It is all executed on launch of the application.
Your string should look like this:
NSString *myString = [NSString stringWithFormat:#"http://myurl.com/%d", myInt];
What you missed: adding the * to indicate a pointer, and thinking that you had to/could first state that the string would have a format and then later state the format. It all happens at once, creating the string with the specified format.
Edited to add NSURL
To create a url you're creating an object of class NSURL, like this:
NSURL *myURL = [[NSURL alloc] initWithString:myString];
And then you create the url request:
NSURLRequest *request = [NSURLRequest requestWithURL:myURL];
And finally, tell your webView to load the request:
[webView loadRequest:request];
For your first part:
NSString *myString = [NSString stringWithFormat:#"http://myurl.com/%d", myInt];
Then, based on a tutorial from iphonesdkarticles.com:
//Create a URL object.
NSURL *url = [NSURL URLWithString:myString];
//URL Request Object
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
//Load the request in the UIWebView.
[webView loadRequest:requestObj];

NSURL fileURLWithPath where NSString has a space

I've looked at quite a few of the related questions and cannot find a similar problem or a solution so my apologies if there is a duplicate out there somewhere.
Anyway, I'm trying to generate a file's NSURL to use with an NSXMLDocument. I have the following components:
const NSString * PROJECT_DIR = #"~/SP\\ BB/";
const NSString * STRINGS_FILE = #"Localizable.strings";
and construct the URL like so:
NSURL * stringsURL = [NSURL fileURLWithPath:[[NSString stringWithFormat:#"%#%#",PROJECT_DIR,STRINGS_FILE] stringByExpandingTildeInPath]];
however, the resulting path in the NSURL is:
file://localhost/Users/timothyborrowdale/SP2B/Localizable.strings
I have tried changing the PROJECT_DIR to
#"~/SP BB/"
#"~/SP\\\\ BB/" (changes to SP엀2B)
#"~/SP%20BB/"
#"~/SP\%20BB/"
with the same problem. I also tried typing out the file url completely and using [NSURL URLWithString:]
I have also tried using stringByAddingPercentEscapesUsingEncoding with both NSUTF8Encoding and NSASCCIEncoding and these have the same issue.
The NSString displays properly before being passed to NSURL or stringByAddingPercentEscapesUsingEncoding but has the problem once outputted from either.
Try this:
NSString *fnam = [#"Localizable" stringByAppendingPathExtension:#"strings"];
NSArray *parts = [NSArray arrayWithPathComponents:#"~", #"SP BB", fnam, (void *)nil];
NSString *path = [[NSString pathWithComponents:parts] stringByStandardizingPath];
NSURL *furl = [NSURL fileURLWithPath:path];
Foundation has a host of platform-independent, path-related methods. Prefer those over hard-coding path extension separators (often ".") and path component separators (often "/" or "\").
Try abandoning stringWithFormat: (never the right answer for stapling paths together) and stringByExpandingTildeInPath and using NSHomeDirectory() and stringByAppendingPathComponent: instead.
#"~/SP\\ BB/" (changes to SP엀2B)
How did you arrive at that conclusion?