Search code examples
objective-ccocoasubclassnssavepanel

Is it possible to subclass NSSavePanel?


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.


Solution

  • 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
                                              ...
                                           }
    
                                        }
    ];