8

I'm working on a screen saver for OSX (Mountain Lion) and I'm having trouble setting up the configuration sheet (so when the user clicks "Screen Saver Options..." within System Preferences, my options appear). There seem to be only two or three tutorials on writing OSX screen savers anywhere on the Internet, and they're all several years old so the material doesn't quite translate to OSX 10.8 and Xcode 4.

First of all, in my ScreenSaverView.m file, I have:

- (BOOL)hasConfigureSheet
{
    return NO;
}

- (NSWindow*)configureSheet
{
    return nil;
}

...and yet, in System Preferences, the "Screen Saver Options..." button is still clickable (nothing happens when it's clicked) rather than disabled as in the "Arabesque" screen saver.

What are the steps to having a configuration sheet appear when the button is clicked, and why is the button not currently disabled?


Edit:

I realized why the "Screen Saver Options..." button wasn't disabled. I had forgotten to include -(BOOL)hasConfigureSheet; in the ScreenSaverView.h file. My question about how to get the configuration sheet to appear, however, remains.

JacobEvelyn
  • 3,901
  • 1
  • 40
  • 51

1 Answers1

7

First things first: Be sure to include ScreenSaver.framework in your project; it provides the necessary classes ScreenSaverView and ScreenSaverDefaults.

You say you already have a file called ScreenSaverView.m. Couple that with you also saying that you have to export your -hasConfigureSheet method in order to make the "Screen Saver Options..." button disable. This leads me to wonder if you have subclassed ScreenSaverView as you should have done. (Did you subclass NSObject instead?) ScreenSaverView exports methods such as -hasConfigureSheet for you. You should be subclassing it, and overriding the appropriate methods in it.

A couple more things:

You should have included a xib file in your project that contains the UI for your configuration sheet, and you should have provided IBOutlets in your subclass' interface to reference the panel and the UI elements it contains (those for which you actually need an outlet, that is).

Finally, your -configureSheet method should fetch the configuration sheet in a manner similar to this (in this example, configSheet would be one of your IBOutlets):

if (configSheet == nil)
{
    if ([NSBundle loadNibNamed:@"myConfigSheet" owner:self] == NO)
    {
        NSLog(@"load config sheet failed");
    }
}

// then retrieve your defaults and set up your sheet; you should
//  be working with ScreenSaverDefaults, a subclass of NSUserDefaults.

// then return 'configSheet'

Edit:

Apologies in advance if I'm about to tell you things you already know, but you did say you were having difficulties in configSheet, and so I'm simply covering all the bases.

In My_ScreensaverView.h, declare an outlet for your panel:

IBOutlet id configSheet;

Note that I used id instead of NSWindow * or NSPanel *, simply because I don't know what class you actually are using for the sheet. (Ideally, a NSPanel should be used for a sheet.)

In your nib file, make sure that the File's Owner is an instance of My_ScreensaverView. You can determine this by selecting the icon for this object and then using the Identity inspector to specify the class.

Make the connection between the configSheet outlet and the panel. One way of doing this is to hold down the Control key while dragging from the File's Owner object to the window or panel icon, then selecting configSheet from the pop-up that appears.

As always, good luck to you in your endeavors.

Extra Savoir-Faire
  • 6,026
  • 4
  • 29
  • 47
  • I do indeed have `ScreenSaver.framework` in my project and I'm subclassing `ScreenSaverView` with `My_ScreensaverView`. Sorry for the confusion. I think my problem is not knowing how to connect `configSheet` in `My_ScreensaverView.h` to the `.xib` file. – JacobEvelyn Dec 05 '12 at 06:15
  • I'm not sure what to tell you. I've had virtually the same code you posted all along, but I don't know how to link `IBOutlet id configSheet` to the `.xib` file itself. I believe one usually ctrl-clicks the element within the `.xib` and drags it to `IBOutlet id configSheet` in the header file, but it isn't working for me. Does that make sense? Can you get it to work for you in Xcode 4? – JacobEvelyn Dec 06 '12 at 16:06
  • @ConstableJoe I understand what you're trying to do, but that's not the way to do it. Control-drag from the object icon representing your My_ScreensaverView (it's identifed as "File's Owner") to the object icon representing your panel. A contextual menu should appear listing `configSheet`. Select `configSheet` from the menu, and you should be good to go. – Extra Savoir-Faire Dec 06 '12 at 16:13
  • @ConstableJoe There's a vertical row of icons to the left of your user interface layout. That's where the icons to which I'm alluding are located. – Extra Savoir-Faire Dec 06 '12 at 16:19
  • Thanks for putting up with my confusion! I see the object icons, but ctrl-dragging from "File's Owner" to the panel object icon does nothing for me. The only ctrl-drag that seems to do anything is from "Application" to "Panel," which opens a menu that says "Outlets" and "Delegate." – JacobEvelyn Dec 06 '12 at 16:43
  • @ConstableJoe Is "File's Owner" an instance of `My_ScreensaverView`? Use the Identity inspector to confirm that. If it isn't, then change it there. You should be able to make the connection from there. – Extra Savoir-Faire Dec 06 '12 at 16:54
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/20702/discussion-between-constablejoe-and-trudyscousin) – JacobEvelyn Dec 06 '12 at 17:02