NicoC
NicoC

Reputation: 65

NSOpenPanel inheritance and "designated initializer"

I am quite new to swift, coming from C++ without background in Obj-C, and I can't find and elegant solution to a small problem...

I use a NSOpenPanel to retrieve some files urls.

My code look likes that :

let import_panel = NSOpenPanel()
import_panel.allowsMultipleSelection = true;
import_panel.canChooseDirectories = false;
import_panel.canCreateDirectories = false;
import_panel.canChooseFiles = true;
let import_panel_delegate = ImportPanelDelegate.init()
import_panel.delegate = import_panel_delegate
import_panel.prompt = NSLocalizedString("IMPORT_BUTTON_TEXT", comment: "")
let i = import_panel.runModal();

I would like to use this import panel at several places in my app, so my first thought is to subclass NSOpenPanel to create an "ImportPanel".

class ImportPanel : NSOpenPanel{
  init()
  {
    super.init()
    self.allowsMultipleSelection = true
    self.canChooseDirectories = false
    self.canCreateDirectories = false
    self.canChooseFiles = true
    self.delegate = ImportPanelDelegate.init()
    self.prompt = NSLocalizedString("IMPORT_BUTTON_TEXT", comment: "")
  }
}

Here, I face a compile error, telling that I should use the "designated initializer" of NSOpenPanel. If I understand well, the designated initializer is an initializer that explicitly set multiple parameters. But here, I don't know which initializer use. Moreover, I don't know how to fill parameters for these different initializers !

I am aware that Swift is more "Protocol oriented programming" than "Object Oriented programming", so maybe subclassing NSOpenPanel was not the right solution, but I can't figure out how to use protocols here.

So, if I want to specialize a NSOpenPanel, how should I do it ?

Thanks by advance !

Upvotes: 2

Views: 219

Answers (1)

CRD
CRD

Reputation: 53010

This is not a general answer, it is specific to NSOpenPanel and NSSavePanel only: Never, ever, attempt to subclass these two classes.

These two classes are special due to how they are part of the sandbox implementation, mess with them and things tend to break.

Instead of subclassing (or, as you mention, protocols - which are not the answer to everything despite what you might read everywhere ;-)) design yourself a type (class or struct) which wraps these classes and provides the functionality you need. I.e. use "has a" rather than "is a".

Alternatively you can write functions which create, or take, an instance of one of these classes and do the customisation you want. I.e. not even "has a" but simply customise an instance using its standard API.

Each approach is equally valid, pick whichever suits the use case.

HTH

Upvotes: 2

Related Questions