Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I set recipients for UIActivityViewController in iOS 6?

I'm using the new UIActivityViewController class in iOS6 to provide the user with various sharing options. You can pass an array of parameters to it such as text, links and images and it does the rest.

How do I define recipients? For example sharing via mail or SMS should be able to accept recipients but I can't figure out how to invoke this behaviour.

I don't want to have to have to use MFMessageComposeViewController and UIActivityViewController separately as that just defeats the purpose of the share controller.

Any suggestions?

UIActivityViewController Class Reference

Edit: This has now been submitted Apple and subsequently merged with a duplicate bug report.

Bug report on OpenRadar

like image 231
MattCheetham Avatar asked Sep 27 '12 14:09

MattCheetham


2 Answers

For adding subject to the email using UIActivityViewController on iOS6, this is the best solution that anyone can use.. All you have to do is call the following while initializing UIActivityViewController.

UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities];
[activityViewController setValue:@"My Subject Text" forKey:@"subject"];

And your UIActivityViewController is populated with a subject.

like image 128
Ajay Avatar answered Nov 05 '22 02:11

Ajay


I just come up with a solution to this problem (in my case set the subject of the email): as internally the UIActivityViewController will call at some point the setMessageBody:isHTML: method of the MFMailComposeViewController class, just intercept that call and inside make a call to the setSubject: method. Thanks to "method swizzling" technic, it looks like:

#import <objc/message.h>

static void MethodSwizzle(Class c, SEL origSEL, SEL overrideSEL)
{
    Method origMethod = class_getInstanceMethod(c, origSEL);
    Method overrideMethod = class_getInstanceMethod(c, overrideSEL);

    if (class_addMethod(c, origSEL, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod))) {
        class_replaceMethod(c, overrideSEL, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    } else {
        method_exchangeImplementations(origMethod, overrideMethod);
    }
}

@implementation MFMailComposeViewController (force_subject)

- (void)setMessageBodySwizzled:(NSString*)body isHTML:(BOOL)isHTML
{
    if (isHTML == YES) {
        NSRange range = [body rangeOfString:@"<title>.*</title>" options:NSRegularExpressionSearch|NSCaseInsensitiveSearch];
        if (range.location != NSNotFound) {
            NSScanner *scanner = [NSScanner scannerWithString:body];
            [scanner setScanLocation:range.location+7];
            NSString *subject = [NSString string];
            if ([scanner scanUpToString:@"</title>" intoString:&subject] == YES) {
                [self setSubject:subject];
            }
        }
    }
    [self setMessageBodySwizzled:body isHTML:isHTML];
}

@end

Call the following line of code before using UIActivityViewController:

MethodSwizzle([MFMailComposeViewController class], @selector(setMessageBody:isHTML:), @selector(setMessageBodySwizzled:isHTML:));

Then pass to the UIActivityViewController a custom UIActivityItemProvider that for UIActivityTypeMail returns a HTML NSString like:

<html><head>
<title>Subject of the mail</title>
</head><body>
Body of the <b>mail</b>
</body></html>

The subject of the email is extracted from the HTML title (use plain text for that part, no html entities or tags).

Using that method, I let you elaborate an elegant way to set the recipient for the mail.

like image 10
Emmanuel Paris Avatar answered Nov 05 '22 01:11

Emmanuel Paris