NSURL path not working, but NSString path working - objective-c

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.

Related

confused by substring result of stringByDeletingLastPathComponent

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);

Why can't NSFIleManager -fileExistsAtPath not find an existing file when path is correct?

I know that the iOS Simulator is found in a different directory each time it is run; with that in mind, I have this code which gives me the directory of the Core Data sqlite files:
// find current directory for saori.sqlite
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentDirectory = [[fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]firstObject];
NSString *sqliteFilePath = [[documentDirectory URLByAppendingPathComponent:#"Application Support/SalonBook/saori.sqlite"] absoluteString];
if ([fileManager fileExistsAtPath:sqliteFilePath])
[MagicalRecord cleanUp]; // set stack, etc to 'nil'
else {
NSLog(#"\n\n-->sqlite files not found"); // log message "unable to find sqlite files
return;
}
This is the printout of the sqliteFilePath object:
Printing description of sqliteFilePath:
file:///Users/rolfmarsh/Library/Developer/CoreSimulator/Devices/1EE69744-255A-45CD-88F1-63FEAD117B32/data/Containers/Data/Application/C8FF20F0-41E4-4F26-AB06-1F29936C2208/Library/Application%20Support/SalonBook/saori.sqlite
And this is the image of the file from Finder:
The problem is: I go to the sqliteFilePath and the saori.sqlite file is indeed there! Why is -fileExistsAtPath failing?
Because it is still a URL. A file path doesn't have a protocol, so the prefix of your path file:/// is invalid and can't be resolved. Since an invalid path doesn't contain any files, fileExistsAtPath: returns NO.
Not to worry though, instead of calling absoluteString on the URL object, you can just call path instead and it will return the path.

Cannot Find File with NSFileManager

Im trying to find a file with NSFileManager. The file exists but my path is never correct no matter how its phrased. The code I'm using is below. Why is NSFileManager not finding the file?
NSString *myFile = #"file1658.pdf";
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:myFile]) {
NSLog(#"good");
}
MyFile is not a full path (e.g., "/Users/Joe/Documents/file1658.pdf"), so NSFileManager is looking for it in the current working directory. You can see what that is with -[NSFileManager currentDirectoryPath].
You need to either include the full path to the file as part of myFile, or set the proper working directory with -[NSFileManager changeCurrentDirectoryPath:].
// If myFile is in "/Users/joe/Documents"...
[fileManager changeCurrentDirectoryPath:#"/Users/joe/Documents"];
if ([fileManager fileExistsAtPath:myFile]) {
NSLog(#"good");
}
Apple tries hard to get you to put your files in sensible places. The file my exist, but you will have to either give the full path, e.g. /Users/user2759189/file1658.pdf or specify what folder it is in by other means.
App bundle
If the file is in your app bundle (for example, you have added it using "Add files to [project]" in XCode) you can get its path by something like:
NSString *myFile = [[NSBundle mainBundle] pathForResource:#"file1658" ofType:#"pdf"];
Search paths
You can look for user documents in a civilised manner by using the foundation function NSSearchPathForDirectoriesInDomains and some built in constants. If the file is in the user's Documents folder, for example, you can use something like:
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *myFile = [documentsPath stringByAppendingPathComponent:#"file1658.pdf"];

Checking if file exists when file on an external device

A playlist file .m3u contains entries available on an external device (a USB key in this case) such as:
/Volumes/KINGSTON/folder/mytitle.mp3
I'd like to check if the file exists:
NSURL *url = [NSURL URLWithString:#"/Volumes/KINGSTON/folder/mytitle.mp3"];
NSFileManager *manager = [NSFileManager defaultManager];
NSLog(#"%d",[manager fileExistsAtPath:[url absoluteString]]); //returns 0. I expect 1
I also tried:
NSURL *u = [[NSURL alloc]initWithScheme:#"/Volumes" host:#"/KINGSTON" path:#"/folder/mytitle.mp3"];
NSLog(#"%d",[manager fileExistsAtPath:[u absoluteString]]); //0
What did I do wrong?
Thanks,
Roland
NSURL *url = [NSURL URLWithString:#"/Volumes/KINGSTON/folder/mytitle.mp3"];
That string does not describe a URL. It's a pathname. Use fileURLWithPath:.
NSLog(#"%d",[manager fileExistsAtPath:[url absoluteString]]);
absoluteString does not return a path; it returns a string describing a URL. Use path.
Or, better yet, use checkResourceIsReachableAndReturnError:.
I also tried:
NSURL *u = [[NSURL alloc]initWithScheme:#"/Volumes" host:#"/KINGSTON" path:#"/folder/mytitle.mp3"];
/Volumes isn't a scheme, /KINGSTON isn't a host, and /folder/mytitle.mp3 is a path but does not refer to anything that exists.
The scheme for a file URL is file:, and the host is generally either localhost or the empty string. The path of a file URL is the complete absolute path to the file.
In your first example, you need to use +[NSURL fileURLWithPath:]. In your second example, I see what you're trying to do, but you're simply going about it the wrong way.
I assume there's a reason you're bothering with NSURL when you have the path you could pass directly to -fileExistsAtPath:?

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.