How to debug a Screensaver in OS X
You can debug plugins by executing the application that will load the plugin.
So to debug a screensaver, open your plugin project, choose New Custom Executable from the Project menu and set the application to be the screensaver engine.
For debugging a screensaver, you might also want to use a second Mac and use remote debugging so your user interface actions don't interfere with the screensaver.
There's a few Mac OS X apps that will run screen savers: SaverLab, Screenalicious, etc. Just find one of them on the web and download it and then set it as the target executable (as Peter N Lewis said).
To avoid copying the build product to '~/Library/Screen Savers/' after each build you can add a custom build script (note: I'm using '/bin/tcsh -x' for the shell):
#remove the old screen saver or link
rm -Rf "${SCRIPT_OUTPUT_FILE_0}"
#if this is a debug build…
if ("${CONFIGURATION}" == "Debug" ) then
# create a symbolic link from our screen saver to this users screen saver directory
ln -sfv "${SCRIPT_INPUT_FILE_0}" "${SCRIPT_OUTPUT_FILE_0}"
#if this is a release build…
else if ("${CONFIGURATION}" == "Release" ) then
# copy our screen saver to this users CMM directory
cp -Rfv "${SCRIPT_INPUT_FILE_0}" "${SCRIPT_OUTPUT_FILE_0}"
endif
Then set its input file to "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}" and its output file to "${HOME}/Library/Screen Savers/${FULL_PRODUCT_NAME}".
Now when you build / run your project it will auto-magicly link to your debug build or copy your release build.
Because of OS X 10.11 El Capitan's System Integrity Protection feature, the debugger can't attach to anything running from /System/
. Also, the other info here applies to old versions of Xcode.
Here's how I got it working on El Capitan with Xcode 7.2:
- Copy
/System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app/
to/tmp/
. (Since the .xcscheme references the fully-qualified path, copying it to someplace common is best for collaboration, instead of to somewhere in a particular user's home directory.) - Edit the project's
.xcscheme
:- Set the Executable for its Run action to the copied app, and add the arguments:
-debug
-background
-module "<product-name>"
(where<product-name>
is the bundle name without the.saver
extension). - Add a Pre-action script (source below), with its shell set to
/bin/bash
and its build settings to come from the scheme. It creates a symbolic link to the built.saver
bundle in~/Library/Screen Savers/
- Set the Executable for its Run action to the copied app, and add the arguments:
Source:
SCREEN_SAVER_PATH="${HOME}/Library/Screen Savers/${FULL_PRODUCT_NAME}"
if [[ -d "${SCREEN_SAVER_PATH}" || -f "${SCREEN_SAVER_PATH}" || -L "${SCREEN_SAVER_PATH}" ]]; then
rm -Rf "${SCREEN_SAVER_PATH}"
fi
ln -s "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}" "${SCREEN_SAVER_PATH}"
Now, when you hit Xcode's Run button, the screen saver will run in wallpaper mode on your Desktop, and you can use the debugger.
There is an old MacTech article that describes the Screen Saver development cycle. There is also a Part 2 to the article. Look in the "Debugging Tips" section.
I find this method a pain so I wrote an application, the basic application was one window and a controller that initialized a ScreenSaverView with my new screensaver bundle. Once that was working all I had to do to test a change was hit Command-R in Xcode.