NSOpenPanel - Everything deprecated?
Asked Answered
H

3

13

I've been trying to get a window to show up asking the person to choose a file, and I eventually did. The problem is, Xcode complains that the method I'm using is deprecated. I looked in the class reference, but everything under the "running panels" section has been deprecated as of Mac OS 10.6. Is there a different class I'm supposed to be using now?

Halophyte answered 7/10, 2011 at 23:56 Comment(0)
D
27

As far as I know, you can use the runModal method like shown below:

NSOpenPanel *openPanel = [[NSOpenPanel alloc] init];

if ([openPanel runModal] == NSOKButton)
{
    NSString *selectedFileName = [openPanel filename];
}
Dougdougal answered 8/10, 2011 at 0:1 Comment(4)
@Halophyte The reason you couldn't find this method is because it is implemented by NSSavePanel, which is NSOpenPanel's superclass. +1Organo
The same is true of the other, better ways of running a save or open panel, including the method for running one as a sheet.Planarian
In Xcode, alt-clicking filename in this code tells me that [openPanel filename] is deprecated as of 10.6. The replacement is [openPanel URLs] (as used in Guillaume's answer).Trabzon
NSOKButton is deprecated: replace with NSModalResponseOK.Triggerfish
D
30

In 10.6, there was a few changes to this classes. One of the benefits is that there is now a block-based API.

Here is a code snippet on how to use that:

NSOpenPanel *panel = [[NSOpenPanel openPanel] retain];

// Configure your panel the way you want it
[panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:NO];
[panel setAllowsMultipleSelection:YES];
[panel setAllowedFileTypes:[NSArray arrayWithObject:@"txt"]];

[panel beginWithCompletionHandler:^(NSInteger result){
    if (result == NSFileHandlingPanelOKButton) {

        for (NSURL *fileURL in [panel URLs]) {
            // Do what you want with fileURL
            // ...
        }
    }

    [panel release];
}];
Disagreement answered 27/12, 2011 at 18:7 Comment(2)
This looks like it's the correct code to use under 10.10, but get rid of the retain and release bits if you're using ARC.Clementineclementis
Alternatively you can use - beginSheetModalForWindow:completionHandler: if you don't want a separate open dialog.Relate
D
27

As far as I know, you can use the runModal method like shown below:

NSOpenPanel *openPanel = [[NSOpenPanel alloc] init];

if ([openPanel runModal] == NSOKButton)
{
    NSString *selectedFileName = [openPanel filename];
}
Dougdougal answered 8/10, 2011 at 0:1 Comment(4)
@Halophyte The reason you couldn't find this method is because it is implemented by NSSavePanel, which is NSOpenPanel's superclass. +1Organo
The same is true of the other, better ways of running a save or open panel, including the method for running one as a sheet.Planarian
In Xcode, alt-clicking filename in this code tells me that [openPanel filename] is deprecated as of 10.6. The replacement is [openPanel URLs] (as used in Guillaume's answer).Trabzon
NSOKButton is deprecated: replace with NSModalResponseOK.Triggerfish
R
5

Seeing how I found this question useful six years later, and since there are no swift answers, here's a swift solution.

You'll find two samples, one as a stand alone window and the other as a sheet.

Swift 3.0

func selectIcon() {
    // create panel
    let panel = NSOpenPanel()

    // configure as desired
    panel.canChooseFiles = true
    panel.canChooseDirectories = false
    panel.allowsMultipleSelection = false
    panel.allowedFileTypes = ["png"]

    // *** ONLY USE ONE OF THE FOLLOWING OPTIONS, NOT BOTH ***

    // ********************** OPTION 1 ***********************
    // use this if you want a selection window to display that is
    // displayed as a separate stand alone window
    panel.begin { [weak self] (result) in
        guard result == NSFileHandlingPanelOKButton, panel.urls.isEmpty == false, let url = panel.urls.first else {
            return
        }

        let image = NSImage.init(contentsOf: url)
        DispatchQueue.main.async {
            self?.iconImageView.image = image
        }
    }

    // ********************** OPTION 2 ***********************        
    // use this if you want a sheet style view that displays sliding
    // down from your apps window
    panel.beginSheetModal(for: self.view.window!) { [weak self] (result) in
        guard result == NSFileHandlingPanelOKButton, panel.urls.isEmpty == false, let url = panel.urls.first else {
            return
        }

        let image = NSImage.init(contentsOf: url)
        DispatchQueue.main.async {
            self?.iconImageView.image = image
        }
    }
}
Rebellion answered 30/6, 2017 at 21:2 Comment(1)
So the .begin is a completion handler. For future on-lookers: You can also do: let response = panel.runModal();if response == NSApplication.ModalResponse.OK {/*do things with panel.url*/} Also works for .CANCELGhats

© 2022 - 2024 — McMap. All rights reserved.