In addition to cut, copy, and paste, Cocoa provides a nearly transparent system for applications to work together called Services. Services work with Cocoa’s concept of “selection” to provide a system for automatically sending information from one application to accomplish a specific function in another.
Services can send information, retrieve it, or do bidirectional processing. For example, say you’re looking at an article in a TextEdit file. To clip a paragraph from the article and place it in a “Sticky” on the desktop, you can simply select the paragraph and choose Services → Make Sticky, as shown in Figure 20-3.
Figure 20-3. The Services menu provides interapplication messaging without prior agreement between applications
Unlike most menus, the Services menu is not controlled by the application in which it appears. Instead, the content of the Services menu is controlled by the operating system.
When a user logs in, the Cocoa environment scans all of the folders listed in Table 20-2 for applications that advertise that they can handle the Services protocol. This advertisement consists of a list of the messages that the program can handle, what kinds of data types it can accept, and what kinds of data types it can return.
If the services for a newly installed application do not appear in your Services menu, try logging out of your computer and logging back in. If that doesn’t work, wait 15 minutes, shut down your computer, start it up again, and log in again. At some point, the services should appear.
For example, the Stickies advertisement is as follows:
NSExecutable: Stickies NSKeyEquivalent: Y NSMenuItem: Make Sticky NSMessage: makeStickyFromTextServices NSPortName: Stickies NSSendTypes: NSStringPboardType, NSRTFPboardType
It’s also possible for an application to have an NSReturnTypes field, but Stickies doesn’t.
The advertisements that an application makes are stored in the
Info.plist
file contained inside the
application’s .app
wrapper
(folder). When a user runs an application, the application sends the
following message to NSApp to register which types it can send and
receive:
(void)registerServicesMenuSendTypes:
(NSArray *)sendTypes
andReturnTypes:
(NSArray *)returnTypes
sendTypes and returnTypes are both NSArrays of NSString objects that are similar to those used by NSPasteboard’s declareTypes:owner: method. After the program starts running, the following method:
(id)validRequestorForSendType:
(NSString *)typeSent
returnType:
(NSString *)typeReturned
is sent down the responder chain for every combination of send and
return types that the application can handle. If a responder can
handle a particular combination, it should return something other
than NULL (such as self
). For example, the
NSTextView class implements this
method, returning self
for the combinations shown
in Table 20-3 and NULL for all others.
Table 20-3. NSTextView send and return types
Send type |
Return type |
Comments |
---|---|---|
NULL |
NSStringPboardType |
Inserts new text |
NULL |
NSRTFPboardType |
Inserts new Rich Text |
NSStringPboardType |
NULL |
Sends text, no return |
NSRTFPboardType |
NULL |
Sends Rich Text, no return |
NSStringPboardType |
NSStringPboardType |
Sends text, gets a response, and replaces the sent text with the received text |
NSStringPboardType |
NSStringPboardType | |
NSStringPboardType |
NSRTFPboardType | |
NSRTFPboardType |
NSStringPboardType | |
NSRTFPboardType |
NSRTFPboardType |
ThevalidRequestorForSendType:returnType: method is invoked often, so it should be as efficient as possible. Normally, it simply looks for combinations of send and return types and returns a value.
When the user selects an item from the Services menu in your application, your object will be sent the writeSelectionToPasteboard:types: message declared as follows:
@interface NSObject(NSServicesRequests) - (BOOL)writeSelectionToPasteboard:
(NSPasteboard *)pboard
types:
(NSArray *)types
; @end
This method is defined by the Application Kit as a category of the
NSObject class, so it can be sent to any object in your application.
Normally, though, it will be sent only to objects that can handle
selection. When this method in an object in your application gets
invoked, it should write whatever is selected to the pasteboard
pboard
. The method should return YES if the data
can be provided and NO if it cannot.
If the service returns data, your object should also implement the readSelectionFromPasteboard: method:
@interface NSObject(NSServicesRequests) - (BOOL)readSelectionFromPasteboard:
(NSPasteboard *)pboard
; @end
If you are creating an object that does not handle selection, you do not need to implement or even worry about these methods. (The NSTextView object is an example of an object that handles selection.) For the remainder of this chapter, we will concentrate solely on the other half of the process — offering services to other applications.
18.227.111.208