How to fill the URLs array of the NSOpenPanel with absolute file path? - objective-c

I am trying to create a panel that lets the user choose a path to save a file. When the user selects a directory from the panel that shows relative path (i.e. /folder) the URLs property is contains /folder. When the user selects a directory that shows the full path, URLs property of panel contains the full path (i.e. /User/name/folder). How do I ensure the URLs property will definitely contain the full paths even though the user's panel shows a relative path?
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseFiles:NO];
[panel setCanChooseDirectories:YES];
[panel setAllowsMultipleSelection:NO]; // yes if more than one dir is allowed
NSInteger clicked = [panel runModal];
NSArray<NSURL *> *URLs;
if (clicked == NSFileHandlingPanelOKButton) {
URLs = [panel URLs];
}
else{
URLs = [NSArray arrayWithObject:[NSURL URLWithString:[NSString stringWithFormat:#"file://%s/", getenv("HOME")]]];
}
for (NSURL *url in URLs) { // When user clicks cancel, [panel URLs] is empty
NSString *selectedDirectoryPath = [url.absoluteString substringFromIndex:6];
// NSString *selectedDirectoryPath = [url path];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *sourceFilePath = [NSString stringWithFormat:#"%#/%#", NSHomeDirectory(), _fileName];
NSString *destFilePath = [NSString stringWithFormat:#"%#%#", selectedDirectoryPath, _fileName];
}
I thought I could use the path instance property on url, but the array is filled once the user clicks OK to a file path with NSFileHandlingPanelOKButton.
Edit: I found a response that suggests to use beginSheetModalForWindow in NSOpenPanel URL to string , but how do you use this function?

I used setDirectoryURL to open the panel to the root folder by default. This will help ensure it returns an absolute path, otherwise a relative path is returned.
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setDirectoryURL:[NSURL URLWithString:[NSString stringWithFormat:#"file:///"]]];

Related

Displaying text in text view from NSArray

This method found in the AppDelagate, loads a text file of my choosing and splits the context of the text file into an array.
Im having trouble displaying the contents of the array in my NSScrollview * called self.textView.
I am not sure how to update the text view with each member of the array.
- (IBAction)loadButton:(id)sender {
NSOpenPanel *panel = [NSOpenPanel openPanel];
if ([panel runModal] == NSFileHandlingPanelOKButton) {
NSURL *bookUrl = [panel URL];
NSString *contents = [NSString stringWithContentsOfURL: bookUrl encoding: NSASCIIStringEncoding error: NULL];
NSArray *loadedBook = [contents componentsSeparatedByString:#"#NP#"];
self.textView.value = loadedBook[0];
}
}
The right method is setString:, which is declared in NSText.
your code should be:
- (IBAction)loadButton:(id)sender {
NSOpenPanel *panel = [NSOpenPanel openPanel];
if ([panel runModal] == NSFileHandlingPanelOKButton) {
NSURL *bookUrl = [panel URL];
NSString *contents = [NSString stringWithContentsOfURL: bookUrl encoding: NSASCIIStringEncoding error: NULL];
NSArray *loadedBooks = [contents componentsSeparatedByString:#"#NP#"];
[self.textView setString:bookStr];
}
}
UPDATE
Take a look at this question, to see how to add text to a NSScrollView

OSX directory with spaces

I'm having an issue with opening directories that have spaces in them. My code looks like this:
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseDirectories:YES];
if ( [openDlg runModal] == NSOKButton )
{
NSArray* files = [openDlg URLs];
NSString* directoryName = [[files objectAtIndex:0] absoluteString];
directoryURL = [files objectAtIndex:0];
NSLog(#"Directory Name: %#", directoryName);
NSArray *directoryArray = [directoryName componentsSeparatedByString:#"/"];
NSString* currentDirectory = [directoryArray objectAtIndex:(directoryArray.count- 2)];
[directoryBox setTitle:currentDirectory];
}
When I select a directory name with spaces the files are not displayed in a table and the output in the NSLog looks like this:
Directory Name:
file://localhost/Users/Rich/Software%20Bisque/
Any ideas?
The -URLs method of of NSOpenPanel returns instances of NSURL, not file system paths. While NSURLs have become the preferred way to refer to files, you can easily change to a file system path by using NSURL's -path method.
Note that there are many methods specific to working with file system paths that are added to NSString in NSPathUtilities.h. You could probably rewrite your code to incorporate those (double-check that I've got your targeted directory okay):
NSArray* files = [openDlg URLs];
NSString* directoryName = [[files objectAtIndex:0] path];
directoryURL = [files objectAtIndex:0];
NSLog(#"Directory Name: %#", directoryName);
// NSArray *directoryArray = [directoryName pathComponents];
// NSString* currentDirectory = [directoryArray objectAtIndex:(directoryArray.count- 2)];
NSString *currentDirectory = [[directoryName stringByDeletingLastPathComponent]
lastPathComponent];
[directoryBox setTitle:currentDirectory];
You could try removing the percent escapes in the directoryName string - I don't think the system needs them there. Something like:
directoryName = [directoryName stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

Use NSOpenpanel and NSfilemanager to find contents of directory

I'm new to objective-c so please excuse my lack of knowledge. I have a snippet of code here that I can't seem to get working properly. What I'd like to do is present a directory selection panel upon a button click. Once the user selects a directory I'd like to make an array of everything in the directory. Eventually I want to use this array to have a list of sub-directories and files (everything in the directory the user selects) to be copied to another location.
I have a warning that says Instance method '-contentsofdirectoryaturl:options:error' not found (return type defaults to id). I'm not exactly sure what that means or how to fix it and I suspect that this is my problem. Any advice provided would be great. Thanks!
- (IBAction)selectfiles:(id)sender {
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setCanChooseDirectories:YES];
[openPanel setCanChooseFiles:NO];
[openPanel setAllowsMultipleSelection:NO];
if ( [openPanel runModal] == NSOKButton ) {
NSArray *accountPath = [openPanel URLs];
NSLog (#"%#", accountPath);
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
NSArray *contents;
contents = [filemgr contentsOfDirectoryAtURL:accountPath options:(NSDirectoryEnumerationSkipsHiddenFiles) error:nil];
}
}
contentsOfDirectoryAtURL: has an additional argument includingPropertiesForKeys: which you have omitted. That is why the compiler warns you. That argument is a list of properties you want to be prefetched. In the simplest case, you can specify an empty array.
Another error is that [openPanel URLs] returns an array of URLs, even if only one item is selected.
So your code should look like this:
NSURL *accountPath = [[openPanel URLs] objectAtIndex:0];
NSLog (#"%#", accountPath);
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
NSArray *contents;
contents = [filemgr contentsOfDirectoryAtURL:accountPath
includingPropertiesForKeys:[NSArray array]
options:(NSDirectoryEnumerationSkipsHiddenFiles)
error:nil];

Problem getting files from folder, error recognizing folder. (Objective c)

I have the user select a folder from an NSOpenPanel. This returns a filepath like: file://localhost/Folder. Here is my code where it all goes wrong:
NSURL *filePath = [openDlg URL]; //OpenDlg is my NSOpenPanel
NSString *s = [filePath absoluteString];
NSLog(#"%#",s);
NSError *error;
NSArray *b = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:s error:&error];
if (error) {
NSLog(#"%#",error);
}
NSLog(#"%lu",b.count);
Here, no matter what folder I select, this error message is sent: The folder “Folder” doesn’t exist." UserInfo=0x10518b320 {NSFilePath=file://localhost/Folder, NSUserStringVariant=(
Folder
), NSUnderlyingError=0x10515d5e0 "The operation couldn’t be completed. (OSStatus error -43.)"}
What is going on?!? If this isn't the best way to do it how can I access all the files inside of a folder?
Try using this method instead:
- (NSArray *)contentsOfDirectoryAtURL:(NSURL *)url includingPropertiesForKeys:(NSArray *)keys options:(NSDirectoryEnumerationOptions)mask error:(NSError **)error
You can just pass in the NSURL without having to convert it into a NSString. To give you an example of how you would use it, see below:
[[NSFileManager defaultManager] contentsOfDirectoryAtURL:filePathURL
includingPropertiesForKeys:[NSArray arrayWithObjects:NSURLNameKey, nil]
options:NSDirectoryEnumerationSkipsHiddenFiles
error:&error];
I can't see how you setup your NSOpenPanel so I will also include an example of how to set that up below:
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result){
if (result == NSFileHandlingPanelOKButton) {
NSArray* urls = [openPanel URLs];
NSURL *url = [urls objectAtIndex:0];
if (url != nil) {
// If you want to convert the path to a NSString
self.filePathString = [url path];
// If you want to keep the path as a NSURL
self.filePathURL = url;
}
}
}];
The above method will get the path to the file or folder after the user has pressed the OK button. Give that a try and see if it works. To further elaborate on why I suggested you use NSURL, here is the explanation that the Apple Documentation gives:
The preferred way to specify the location of a file or directory is to use the NSURL class. Although the NSString class has many methods related to path creation, URLs offer a more robust way to locate files and directories. For applications that also work with network resources, URLs also mean that you can use one type of object to manage items located on a local file system or on a network server.

Get filepath File Open Dialog box cocoa?

I have a File Open Dialog box in my application to select files from, but when the user clicks the 'Select' button in the box, it obviously won't do anything. How do I extract the filepath from the selected file? I need the filepath so I can get the contents of the file to encrypt. Initially, I hard coded the file I would use into my application, but that was only for testing purposes. Here is what I am using for the File Open Dialog Box:
int i;
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseFiles:YES];
[openDlg setCanChooseDirectories:YES];
[openDlg setPrompt:#"Select"];
NSString *fileName = [pathAsNSString lastPathComponent];
[fileName stringByDeletingPathExtension];
if ([openDlg runModalForDirectory:nil file:nil] == NSOKButton )
{
NSArray* files = [openDlg filenames];
for( i = 0; i < [files count]; i++ )
{
[files objectAtIndex:i];
}
}
Thanks so much for the help.
Use - (NSArray *)URLs method instead of filenames.
Your code is already handling the files that the user has selected, you're just not doing anything with them.
The array returned from the ‑filenames method contains the paths to the files that the user selected as NSString objects. If they have only selected one file, there will only be one object in the array. If they have selected no files, the array will be empty.
if ([openDlg runModalForDirectory:nil file:nil] == NSOKButton )
{
NSArray* files = [openDlg filenames];
for(NSString* filePath in [openDlg filenames])
{
NSLog(#"%#",filePath);
//do something with the file at filePath
}
}
If you only want the user to be able to select a single file, then call [openPanel setAllowsMultipleSelection:NO] when you're configuring the panel. That way, there will be a maximum of one entry in the filenames array.
As #VenoMKO points out, the ‑filenames method is now deprecated and you should use the ‑URLs method instead. This will return an array of file NSURL objects rather than an array of NSStrings. Since pretty much all the file handling APIs in Snow Leopard were revised to take URLs, this would be the preferred option.
You Want to Get File Path Using Following Code
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
[openPanel setCanChooseFiles:YES];
[openPanel setCanChooseDirectories:NO];
[openPanel setAllowsMultipleSelection: NO];
[openPanel setAllowedFileTypes:ArrExtension ];
if ([openPanel runModal] == NSOKButton ){
NSString *FilePath = [NSString stringWithFormat:#"%#",[openPanel URL]];
[openPanel canHide];
}