Which framework do I need to import for using NSOpenPanel class in Objective-C? - 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.

Related

Getting filename from NSOpenPanel dialog

It's been a year since I last played with Cocoa and it seems a lot has changed.
I am trying to run an open dialog and retrieve the file path. This used to be very simple but now...
The code is:
-(NSString *)getFileName{
NSOpenPanel* panel = [NSOpenPanel openPanel];
__block NSString *returnedFileName;
// This method displays the panel and returns immediately.
// The completion handler is called when the user selects an
// item or cancels the panel.
[panel beginWithCompletionHandler:^(NSInteger result){
if (result == NSFileHandlingPanelOKButton) {
NSURL* theDoc = [[panel URLs] objectAtIndex:0];
// Open the document.
returnedFileName = [theDoc absoluteString];
}
}];
return returnedFileName;
}
-(IBAction)openAFile:(id)sender{
NSLog(#"openFile Pressed");
NSString* fileName = [self getFileName];
NSLog(#"The file is: %#", fileName);
}
(The indentation has been screwed up in the post but it's correct in the code)
My problem is that the final NSLog statement is being executed as soon as the open dialog opens and not waiting until the dialog closes. That leaves the fileName variable null which is what the final NSLog reports.
What is causing this?
Thanks.
There is a similar question to yours:
How do I make my program wait for NSOpenPanel to close?
Maybe
[openPanel runModal]
helps you. It waits until the user closes the panel
The stuff I had written a year ago used runModal so on Christoph's advice I went back to that.
It would appear that the beginWithCompletionHandler block is unnecessary, at least in this case. Removing it also had the advantage of removing the necessity to use the __block identifier.
The following now works as required
-(NSString *)getFileName{
NSOpenPanel* panel = [NSOpenPanel openPanel];
NSString *returnedFileName;
// This method displays the panel and returns immediately.
// The completion handler is called when the user selects an
// item or cancels the panel.
if ([panel runModal] == NSModalResponseOK) {
NSURL* theDoc = [[panel URLs] objectAtIndex:0];
// Open the document.
returnedFileName = [theDoc absoluteString];
}
return returnedFileName;
}
And well done Apple for deprecating the obvious and easy and replacing it with increased complexity.

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

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.

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.

Trouble creating Security-Scoped Bookmark

I'm converting my Lion app to use the App Sandbox. I'm trying to make use of the security-scoped bookmarks feature introduced in 10.7.3 to allow persistent access to a folder. The code I have below returns a nil bookmark, and produces the following log message: XPC couldn't look up the Mach service for scoped bookmarks agent.
I set the User Selected File Access entitlement to Read/Write Access, and also tried with and without the surrounding ..AccessingSecurityScopedResource calls.
I think I'm doing everything right according to the documentation, so I'd appreciate any pointers. The code was working to retrieve a plain URL before I began sandboxing the app.
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setCanChooseFiles:NO];
[openPanel setCanChooseDirectories:YES];
[openPanel setAllowsMultipleSelection:NO];
NSInteger result = [openPanel runModal];
if( result == NSFileHandlingPanelCancelButton ) {
return;
}
NSArray *urls = [openPanel URLs];
if( urls != nil && [urls count] == 1 ) {
NSURL *url = [urls objectAtIndex:0];
NSData *bookmark = nil;
NSError *error = nil;
bookmark = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
includingResourceValuesForKeys:nil
relativeToURL:nil // Make it app-scoped
error:&error];
if (error) {
NSLog(#"Error creating bookmark for URL (%#): %#", url, error);
[NSApp presentError:error];
}
NSLog(#"bookmark: %#", bookmark);
}
Update (x3)
Now that I got it working, I can verify that the calls to -startAccessingSecurityScopedResource and -stopAccessingSecurityScopedResource are not necessary in the code above, since the Powerbox grants access to the resource after the user selects it in the NSOpenPanel.
If you're creating a bookmark from another security-scoped URL, such as making a document-scoped bookmark from an app-scoped bookmark created in another app session, then you need to get access to the file first.
It turns out I was missing a crucial entitlement, not listed in the UI, but listed in the documentation:
com.apple.security.files.bookmarks.app-scope
Update 12/18/2018
According to this Twitter thread, this entitlement may not be required anymore. Thanks #pkamb for alerting me to this.

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