Cocoa Tips: Exposing System Services
One of the things that sets an application apart from the competition is how well it integrates with the environment. Things like drag and drop between applications are expected to just work on OS X. System Services take this a step further.
The services mechanism is something that Apple inherited from NeXT. On NeXTSTEP, it was a top-level menu in every application, while OS X hides it in the application menu. With 10.6, the services menu has been improved, making it easier for users to hide services that they never use and only displaying services that are relevant to the current selection.
The basic idea of a service is similar to a UNIX pipe. A lot of command-line tools can be used as either stand-alone interactive programs, or as filters. When you use them as filters, they process some input from the standard input stream and emit a processed version on the standard output.
The limitation of UNIX filters is that pipes just transmit a stream of bytes. It is up to the user to make sure that the input is provided in a format that the filter can understand. Services work along the same lines but use pasteboards instead of pipes. A service takes a pasteboard as input and returns a pasteboard as output.
Pasteboards on OS X are effectively shared dictionaries. They store a set of different types and data. If you copy some text from TextEdit, for example, you might get RTF data and plain text in a few encodings copied.
Services and Applications
Any OS X application can expose services, and you can put services in stand-alone bundles that will be run on demand. Sometimes you even use the services mechanism for launching an application. There are a few examples of this included with OS X. The one that I use the most is the ISA reference. When at all possible, I try to avoid programming in assembly languages, but sometimes I fail. When I'm reading some assembly code and come across and instruction that I'm not familiar with, I can just select it, go to the services menu, and look up the documentation with the ISA reference service.
Other services exist in isolation. The Equation Service, for example, interprets text on the pasteboard as a LaTeX formula and returns a typeset PDF of the result. You can use this with Keynote to insert beautifully typeset mathematical formulae.
Sometimes it's not clear whether something should be a service or an application. For example, consider the calculator application. A lot of the time that you use this you simply want to do a quick sum. Launching the application, switching to it, and switching back, takes a significant amount of the total time to get the result. As of 10.5 it's often faster to type the sum into the spotlight query box, but this doesn't give a good way of copying the result out again.
Now imagine if the calculator exposed a service. If you wanted to compute a sum, you'd just type it, select it, and go to the evaluate service. You could even assign a shortcut key to this service if you used it frequently, allowing you to use it without touching the mouse.
Deciding which parts of your application to export as services, if any, can be a tricky problem. Some applications don't do anything that might be usefully exposed as a service. Others may want to expose a lot of different services.
Think carefully before you expose a lot of different services. The services menu is shared between all programs in the system and can very quickly become cluttered. Snow Leopard made it easy to remove things from the menu, but that's not an excuse to fill it with hundreds of things and expect the user to turn them all off. Before implementing a service, think about whether it could be better provided by a different user interface. A few of the services that Apple's standard applications provide do exactly the same thing as dropping the selection on the app's icon. This is much easier and faster to do than finding the service in the menu, so the service does nothing more than add clutter to the menu.