1

I am wondering if there is a way to subclass NSSavePanel. Or if you were to create a dummy object, how would you mimic the beginSheetModalForWindow:CompletionHandler function of NSSavePanel?

-(void)beginSheetModalForWindow:(NSWindow *)window completionHandler:(void (^)(NSInteger *))handler{

I am blanking out on how to implement the block handler when implementing the function in the .m class file.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
Dan68am
  • 17
  • 3
  • 1
    What are you actually trying to accomplish? Why do you want to subclass NSSavePanel? – Andrew Madsen Oct 09 '13 at 20:09
  • Just working with a plugin that requires one to be returned. I mainly just want to recreate the beginsheetmodalforwindow from NSSavePanel. – Dan68am Oct 09 '13 at 20:29
  • 1
    @Dan68am - What do you mean "how to implement the block handler"? If you write a method that takes a block then in the method you just call the block using standard function call syntax, you don't "implement" the block. – CRD Oct 09 '13 at 23:48

1 Answers1

3

Short Answer: No

Longer Answer: Here Be Dragons

It is possible but stuff will probably break. You can also add methods using a category and they might work, or they might not. The problems arise due to the way NSOpenPanel is implemented to support the App Sandbox - various chicanery is going on behind the scenes and even convenience category methods which just call existing methods on the class can result in errors being reported by OS X and dialogs not to appear. NSOpenPanel is a delicate creature that should be touched as little as possible and only ever with great care.

Wrapping an NSOpenPanel instance in another class is a different story and should not upset it at all. Go that route.

Addendum re: Comment

The declaration of beginSheetModalForWindow is:

- (void)beginSheetModalForWindow:(NSWindow *)window completionHandler:(void (^)(NSInteger result))handler

The completion handler gets passed a value indicating which button was pressed. To take action dependant on that you can use a standard if:

NSOpenPanel *openPanel;
NSWindow *hostWindow;
...
[openPanel beginSheetModalForWindow:hostWindow
                  completionHandler:^(NSInteger returnCode)
                                    {
                                       if (returnCode == NSFileHandlingPanelOKButton)
                                       {
                                          // OK pressed
                                          ...
                                       }
                                       else
                                       {
                                          // Cancel pressed
                                          ...
                                       }

                                    }
];
CRD
  • 52,522
  • 5
  • 70
  • 86
  • I will check this as the answer because you have answered the general question. I think I do not have a good understanding of block methods as arguments which is my problem. I want the completion handler to do something when a Cancel button is pressed, or NSOKButton. So `if(handler == NSOKButton){` do something. – Dan68am Oct 10 '13 at 15:01
  • @Dan68am - Added an addendum, HTH. – CRD Oct 10 '13 at 17:16
  • Thank you for the in depth answer. Helps me understand this much better – Dan68am Oct 11 '13 at 14:38
  • it is really sad that we cannot customize NSSavePanel – Just a coder Oct 25 '19 at 09:57
  • @iOSCalendarpatchthecode.com – you can *customize* the standard open/save dialogs by adding a [custom view](https://developer.apple.com/documentation/appkit/nssavepanel/1525544-accessoryview?language=objc). What you can't easily do is *subclass* them and change the behavior - this disallowed to protect the sandbox restrictions. – CRD Oct 25 '19 at 11:21
  • ok. I was a bit vague, I meant customize it to do something as simple as this https://stackoverflow.com/questions/58550993/nssavepannel-how-to-restrict-user-to-only-save-one-one-set-directory – Just a coder Oct 25 '19 at 13:36