Reputation: 31
I'm trying to create a swift macOS screensaver with a configurationSheet loading a xib option page. Unfortunately the option page shows only up after clicking the "Screen Saver Options..." button twice. The first time the button is clicked the Console app shows:
-[LegacyExtensionManager exceptionHandler:shouldHandleException:mask:] -- Module: ScreenSaverS threw an uncaught exception: NSInternalInconsistencyException, reason: cannot begin sheet a second time.
-[LegacyExtensionManager processExtensionRequest:replyInfo:]_block_invoke -- Module: ScreenSaverS (ScreenSaverS) failed to display a configuration sheet. Exception: NSInternalInconsistencyException, reason: cannot begin sheet a second time
After this the internal option page seems to be deleted and the second time the options button is clicked my xib loader as well as the complete option page actions works correct. Here is my configurationSheet overload:
override var configureSheet: NSWindow?
{
NSLog("ScreenSaverS:configureSheet self=%p", self);
if (configSheet == nil)
{
let tmpBundle = Bundle(for: type(of: self));
if (tmpBundle.loadNibNamed("ConfigView", owner: self, topLevelObjects: nil) == false)
{
NSLog("ScreenSaverS:configureSheet load config sheet failed");
} else {
NSLog("ScreenSaverS:configureSheet config sheet loaded configSheet=%p", configSheet);
}
} else {
NSLog("ScreenSaverS:configureSheet self=%p already created", self);
}
return configSheet
}
Does anyone have an idea why the first click of the options button lead to this exception and how I can fix this to get it working the first time?
Upvotes: 3
Views: 575
Reputation: 118
When you load your nib, you are passing owner: self
, this should be the controller for your sheet instead.
I would suggest making a separate class for your sheet controller like this :
class ConfigureSheetController : NSObject {
@IBOutlet var window: NSWindow?
@IBOutlet var canvasColorWell: NSColorWell!
override init() {
super.init()
let myBundle = Bundle(for: ConfigureSheetController.self)
myBundle.loadNibNamed("ConfigureSheet", owner: self, topLevelObjects: nil)
}
// ...
Then in the ScreenSaverView you can simply do :
lazy var sheetController: ConfigureSheetController = ConfigureSheetController()
// ...
override var hasConfigureSheet: Bool {
return true
}
override var configureSheet: NSWindow? {
return sheetController.window
}
You can find a complete minimal example of a Swift screen saver here: https://github.com/glouel/ScreenSaverMinimal
Upvotes: 2