Using services to email file in document based app

  • Hi, I would like my document based app to be able to send its files as email attachments. I notice that the Finder has the services option to send a file as an attachment, and kind of thought that something like that might have been built in to the document architecture, but apparently not. It does appear to be a standard service that is available and listed in the system preferences.

    I assumed that if I wanted to try this out, I should be able to do something like this in my NSDocument subclass:

    + (void)initialize {
        [NSApp registerServicesMenuSendTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSFileContentsPboardType, NSURLPboardType, NSFilesPromisePboardType, nil] returnTypes:nil];
    }

    - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType {
        return nil;
    }

    - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types {
        return NO;
    }

    (assuming that the "New Email With Attachment" service would take one of the pasteboard types I had specified). I then put breakpoints in the other two methods, but they were never called.

    I realize that there are other ways that something like this could be accomplished, but seeing as the service is there, I wanted to try to get it working that way.

    Can anyone enlighten me on how this is supposed to be done?

    Thanks

    Gideon
  • On May 11, 2012, at 2:09 AM, Gideon King wrote:

    > I assumed that if I wanted to try this out, I should be able to do something like this in my NSDocument subclass:
    >
    > + (void)initialize {
    > [NSApp registerServicesMenuSendTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSFileContentsPboardType, NSURLPboardType, NSFilesPromisePboardType, nil] returnTypes:nil];
    > }
    >
    > - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType {
    > return nil;
    > }
    >
    > - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types {
    > return NO;
    > }
    >
    > (assuming that the "New Email With Attachment" service would take one of the pasteboard types I had specified).

    That service is defined in Mail's Info.plist and it takes NSFilenamesPboardType.

    > I then put breakpoints in the other two methods, but they were never called.

    The Services docs say that the latter two methods must be on an NSResponder object, like a view or window.  I recognize that the document is in the responder chain for action messages, but that may not suffice for this case.  The docs also say:

    "The validRequestorForSendType:returnType: message is sent along an abridged responder chain, comprising only the responder chain for the key window and the application object."

    Regards,
    Ken
  • Thanks Ken, moving it to my window controller got my validRequestorForSendType called, but the services menu now shows up with just one item: "Notebook Clipping Setup".

    So as it stands, this is my code:

    + (void)initialize {
        [NSApp registerServicesMenuSendTypes:[NSArray arrayWithObject:NSFilenamesPboardType] returnTypes:nil];
    }

    - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType {
        if ([sendType isEqualToString:NSFilenamesPboardType]) {
            NSDocument *d = [self document];
            if ([d fileURL] && ![[self window] isDocumentEdited]) {
                return self;
            }
        }
        return nil;
    }

    - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types {
        if ([types containsObject:NSFilenamesPboardType]) {
            NSDocument *d = [self document];
            if ([d fileURL] && ![[self window] isDocumentEdited]) {
                [pboard setString:[[d fileURL] path] forType:NSFilenamesPboardType];
                return YES;
            }
        }
        return NO;
    }

    With this type registeredI see that the validRequestorForSendType is called asking for the following types:
    com.apple.flat-rtfd
    dyn.agu8y6y4grf0gn5xbrzw1gydcr7u1e3cytf2gn
    NeXT Rich Text Format v1.0 pasteboard type
    NeXT RTFD pasteboard type
    NSFilenamesPboardType
    NSStringPboardType
    public.rtf
    public.utf8-plain-text

    If I have a dirty document, or one that has just been created, the services menu is empty as expected. However, when I have a saved document selected, the only item that shows up is the notebook clipping setup.

    Seeing as the service I want to be available is specified in the mail info.plist using the NSFilenamesPboardType, I'm not sure where else the problem could lie.

    Anyone have any other suggestions?

    Thanks

    Gideon

    On 11/05/2012, at 7:17 PM, Ken Thomases wrote:

    >
    > That service is defined in Mail's Info.plist and it takes NSFilenamesPboardType.
    >
    >> I then put breakpoints in the other two methods, but they were never called.
    >
    > The Services docs say that the latter two methods must be on an NSResponder object, like a view or window.  I recognize that the document is in the responder chain for action messages, but that may not suffice for this case.  The docs also say:
    >
    > "The validRequestorForSendType:returnType: message is sent along an abridged responder chain, comprising only the responder chain for the key window and the application object."
    >
    > Regards,
    > Ken
    >
previous month may 2012 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today