In Cocoa on OS X, what use interface component allows the user to select a new file? - objective-c

I understand how to use an NSOpenPanel to allow the user to select one or more existing files or directories, using a filename suffix. E.g.:
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
openPanel.canChooseFiles = YES;
openPanel.canChooseDirectories = NO;
openPanel.allowsMultipleSelection = NO;
openPanel.allowedFileTypes = #[#"sqlite3"];
However, I would like to know if there is a component that allows the user to select a new file. That is, they select a directory from the NSOpenPanel and type in a filename. Is there a pre-built component for this?

Use the NSSavePanel component.
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSSavePanel_Class/index.html.

Related

Which framework do I need to import for using NSOpenPanel class in Objective-C?

I want to Open File Dialog in my application to upload a particular selected file onto the server in Objective-C. I am using the following code in my application, but it seems to give an error while creating an object of NSOpenPanel.
Please help me out.
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
openPanel.title = #"Choose a .TXT file";
openPanel.showsResizeIndicator = YES;
openPanel.showsHiddenFiles = NO;
openPanel.canChooseDirectories = NO;
openPanel.canCreateDirectories = YES;
openPanel.allowsMultipleSelection = NO;
openPanel.allowedFileTypes = #[#"txt", #"jpg", #"jpeg", #"zip", #"png"];
[openPanel beginSheetModalForWindow:appDelegate.controlsWindow
completionHandler:^(NSInteger result) {
if (result==NSOKButton) {
NSURL *selection = openPanel.URLs[0];
NSString* path = [selection.path stringByResolvingSymlinksInPath];
//do something with the file at "path"
}
}];
NSOpenPanel doesn't exist on iOS. The whole concept of files is pretty well hidden from users in most cases. What's the end goal here? What kind of "files" do you want to upload to a server?
UIKit has the UIImagePickerController, which you can use to select images from the Photo Library, for instance.

NSSavePanel not saving on desktop?

can i use NSSavePanel with a sandboxed OS X app to let user save on desktop? i gave user read/write entitlements for downloads and user selected folder, for some reason my app saves in downloads folder fine but when i change directory and select desktop it doesnt save at all.
here is the code am using for NSSavePanel
if([self.mActiveQRFileName isEqualToString:kQR_DEFAULT_FILE_NAME])
{
NSSavePanel *savePanel = [NSSavePanel savePanel];
//[savePanel setDirectoryURL:[NSURL URLWithString:[Utilities getQRDefaultDirectoryPath]]];
[savePanel setNameFieldStringValue:kQR_DEFAULT_FILE_NAME];
[savePanel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) {
if (result == NSFileHandlingPanelOKButton) {
NSString *qrFilePath = [NSString stringWithFormat:#"%#.%#",[[savePanel URL] path],kQR_FILE_EXT];
[qrd saveQRFile:qrFilePath];
self.mActiveQRFileName = [NSString stringWithString:qrFilePath];
blnChangesSaved = YES;
}
}];
}
else
{
[qrd saveQRFile:self.mActiveQRFileName];
blnChangesSaved = YES;
}
Any help would be greatly appreciated :)
A NSSavePanel will give you the user selected path for a file in it's URL property. The sandbox will only grant you access to this file, with the name specified by the user.
In your example code this line possibly modifies the selected path by giving it a different file extension:
NSString *qrFilePath = [NSString stringWithFormat:#"%#.%#",[[savePanel URL] path],kQR_FILE_EXT];
Which could result in a filename different from the originally selected file for which you don't have access in the sandbox. Try logging the qrFilePath and see if it still equals the path for the selected URL. Also check your sandbox exceptions to see what the exact error is.
If you want to restrict the NSSavePanel to let the user only specify files of a certain type use the setAllowedFileTypes: methos.
If you want the user to grant you access to a directory to write to where you can output any file, as opposed to a specific path: use a NSOpenPanel. This has the disadvantage that the user cannot specify a specific file name like in a NSSavePanel.

Objective-C Directory Picker ( OSX 10.7 )

So I currently have this bit of code to get a dir:
-(NSString *)get {
NSOpenPanel *gitDir = [NSOpenPanel openPanel];
NSInteger *ger = [gitDir runModalForTypes:nil];
NSString *Directory = [gitDir directory];
return Directory;
}
But it gives me errors and says it has now been depreciated.
Is there a better way for OSX 10.7?
This is a supplement to sosborn's answer, not a replacement.
runModalForTypes: is deprecated, and the correct replacement is runModal (or setAllowedFileTypes: followed by runModal, but in this case you're passing nil for the types).
directory is also deprecated, and the correct replacement is directoryURL. (If you actually must return an NSString path rather than an NSURL, just return [[gitDir directoryURL] path].)
However, what you're doing is asking the user to select a file, and then returning the directory that file is in, when what you really want is to ask the user to select a directory. To do that, you want to call setCanChooseFiles to NO and setCanChooseDirectories to YES, and then call URLs to get the directory the user selected.
Also, you're ignoring the result of runModal (or runModalForTypes:). I'm sure the compiler is warning you about the unused variable "ger", and you shouldn't just ignore warnings. If the user cancels the panel, you're going to treat that as clicking OK, and select whatever directory she happened to be in when she canceled.
Here's a better implementation, which will return the URL of the selected directory, or nil if the user canceled (or somehow managed to not select anything). Again, if you need an NSString, just add a "path" call to the return statement:
-(NSURL *)get {
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setAllowsMultipleSelection:NO];
[panel setCanChooseDirectories:YES];
[panel setCanChooseFiles:NO];
if ([panel runModal] != NSModalResponseOK) return nil;
return [[panel URLs] lastObject];
}
Whenever you see a deprecation warning you should go straight to the official documentation. In this case, the docs for NSOpenPanel say:
runModalForTypes: Displays the panel and begins a modal event loop
that is terminated when the user clicks either OK or Cancel.
(Deprecated in Mac OS X v10.6. Use runModal instead. You can set
fileTypes using setAllowedFileTypes:.)
I adapted the code by abarnert for swift. tx for the code just what I needed.
func askUserForDirectory() -> NSURL? {
let myPanel:NSOpenPanel = NSOpenPanel()
myPanel.allowsMultipleSelection = false
myPanel.canChooseDirectories = true
myPanel.canChooseFiles = false
if ( myPanel.runModal() != NSFileHandlingPanelOKButton ) {
return nil
}
return myPanel.URLs[0] as? NSURL
}

NSOpenPanel's setDirectoryURL doesn't work

I'm trying to use the new methods for NSOpenPanel and set its initial directory. The problem is that it only works at the first time and after that it just "remembers" the last selected folder, which I don't want. I have to use the depreciated runModalForDirectory:file: to make it work. It's less than ideal because it was deprecated at 10.6, but thankfully it still works on Lion.
My code is:
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setAllowedFileTypes:[NSArray arrayWithObjects: #"jpg",#"JPG",#"png", nil]];
panel.canChooseDirectories = YES;
panel.allowsMultipleSelection = YES;
handler = ^(NSInteger result) {stuff};
[panel setDirectoryURL:[NSURL URLWithString:#"/Library/Desktop Pictures"]];
There are a couple things to look into:
~/Pictures is not a valid URL. file:///Users/user/Pictures is. -[NSURL URLWithString:] requires a valid URL. You probably want to use -[NSURL fileURLWithPath:] instead. It will turn /Users/user/Pictures into file:///Users/user/Pictures.
Tildes are not automatically expanded, so you want to use [#"~/Pictures stringByExpandingTildeInPath] to get an actual file path.
Put together, change the last line to:
[panel setDirectoryURL:[NSURL fileURLWithPath:[#"~/Pictures" stringByExpandingTildeInPath]]];
I think that should work.
The panel in Lion expects an URL like: file://localhost/Library/Desktop Pictures, but your URL starts with the actual path.
Use [NSURL fileURLWithPath:#"/Library/Desktop Pictures"] instead.
Happy coding!

Cocoa Button Launch outside Application

I have the following setup:
A grid of 4x4 (16 total) buttons (standard NSButton buttons) in an NSWindow.
The NSWindow will come to the front when I press a hotkey combination (DDHotKey)
Now, what I'd like to do is give my buttons the following functionality:
When the button is clicked, open a dialog that shows the /Applications/ directory and allow me to select any of the applications listed there.
When the application is selected store it in a variable (I'm guessing) (or string?) and make it so that when the buttons Key Equivalent is pressed, that application launches
I'm looking around and I'm not exactly sure what to do or really where to begin looking...any clues?
I have this in my appdelegate.m file:
- (void)openDoc:(id)sender
{
int result;
NSArray *fileTypes = [NSArray arrayWithObject:#"td"];
NSOpenPanel *oPanel = [NSOpenPanel openPanel];
[oPanel setAllowsMultipleSelection:YES];
result = [oPanel runModalForDirectory:NSHomeDirectory()
file:nil types:fileTypes];
if (result == NSOKButton) {
NSArray *filesToOpen = [oPanel filenames];
int i, count = [filesToOpen count];
for (i=0; i<count; i++) {
NSString *aFile = [filesToOpen objectAtIndex:i];
id currentDoc = [[ToDoDoc alloc] initWithFile:aFile];
}
}
}
How do I link the button to it?
You can use an NSOpenPanel to choose the application.
Then to launch the application, take a look at this stack overflow question.
store the path to application, then when you want to open them. You can use the system() function.
system("open -a /Applications/someApplication.app");