Iphone 如何在iOS 6中设置UIActivityViewController的收件人?

Iphone 如何在iOS 6中设置UIActivityViewController的收件人?,iphone,objective-c,ios6,uiactivityviewcontroller,Iphone,Objective C,Ios6,Uiactivityviewcontroller,我正在使用iOS6中新的UIActivityViewController类为用户提供各种共享选项。您可以向它传递一组参数,如文本、链接和图像,其余的由它完成 如何定义收件人?例如,通过邮件或短信共享应该能够接受收件人,但我不知道如何调用这种行为 我不想必须分别使用MFMessageComposeViewController和UIActivityViewController,因为这会破坏共享控制器的功能 有什么建议吗 编辑:该文件现已提交给苹果,随后与一份重复的错误报告合并。 您应该能够将使用N

我正在使用iOS6中新的
UIActivityViewController
类为用户提供各种共享选项。您可以向它传递一组参数,如文本、链接和图像,其余的由它完成

如何定义收件人?例如,通过邮件或短信共享应该能够接受收件人,但我不知道如何调用这种行为

我不想必须分别使用
MFMessageComposeViewController
UIActivityViewController
,因为这会破坏共享控制器的功能

有什么建议吗

编辑:该文件现已提交给苹果,随后与一份重复的错误报告合并。


您应该能够将使用NSUrl对象的收件人包括在mailto:scheme(或sms:for text messages)中

从UIActivity类参考中:

UIActivityTypeMail 对象将提供的内容发布到新的 电子邮件。使用此服务时,您可以提供NSString和 UIImage对象和NSURL对象指向本地文件作为 活动项目。您还可以指定其内容的NSURL对象 使用mailto方案

因此,类似的方法应该有效:

NSString *text = @"My mail text";
NSURL *recipients = [NSURL URLWithString:@"mailto:foo@bar.com"];

NSArray *activityItems = @[text, recipients];

UIActivityViewController *activityController =
                    [[UIActivityViewController alloc]
                    initWithActivityItems:activityItems
                    applicationActivities:nil];

[self presentViewController:activityController
                   animated:YES completion:nil];

虽然目前设置电子邮件主题和正文的mailto:解决方案似乎不起作用,但如果您想将电子邮件正文设置为包含HTML,并且仍然通过UIActivityViewController使用苹果的系统电子邮件图标,这在任何情况下都是不够的

UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities];
[activityViewController setValue:@"My Subject Text" forKey:@"subject"];
这正是我们想要做的:使用系统图标,但让电子邮件包含HTML正文和自定义主题

我们的解决方案有点像黑客,但至少目前效果不错。它确实涉及到使用MFMailComposeViewController,但它仍然允许您在UIActivityViewController中使用系统邮件图标

步骤1:创建符合UIActivityItemSource的包装类,如下所示:

    @interface ActivityItemSource : NSObject <UIActivityItemSource>
    @property (nonatomic, strong) id object;
    - (id) initWithObject:(id) objectToUse;
    @end

    @implementation ActivityItemSource

   - (id) initWithObject:(id) objectToUse
    {
        self = [super init];
        if (self) {
            self.object = objectToUse;
        }
        return self;
    }


    - (id)activityViewController:(UIActivityViewController *)activityViewController                 itemForActivityType:(NSString *)activityType
    {
    return self.object;
    }

    - (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
    {

        return self.object;
    }
    @interface ActivityViewController : UIActivityViewController         <MFMailComposeViewControllerDelegate>

    @property (nonatomic, strong) id object;

    - (id) initWithObject:(id) objectToUse;
    @end


    @implementation ActivityViewController

    - (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
    {

        switch (result)
        {
            case MFMailComposeResultSent:
            case MFMailComposeResultSaved:
                //successfully composed an email
                break;
            case MFMailComposeResultCancelled:
                break;
            case MFMailComposeResultFailed:
                break;
        }

    //dismiss the compose view and then the action view
        [self dismissViewControllerAnimated:YES completion:^() {
            [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];        
        }];

    }

    - (id) initWithObject:(id) objectToUse
    {

        self = [super initWithActivityItems:[NSArray arrayWithObjects:[[ActivityItemSource alloc] initWithObject:objectToUse], nil] applicationActivities:nil];

        if (self) {
            self.excludedActivityTypes = [NSArray arrayWithObjects: UIActivityTypePostToWeibo, UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, nil];

            self.object = objectToUse;
        }
        return self;
    }
mailComposeControllerWithObject
方法中,实例化MFMailComposeViewController类的实例,并将其设置为包含所需的任何数据。还请注意,您可以将
activityViewController
设置为compose视图的委托

这样做的原因是,当显示合成模式时,它会阻止显示其他模式,即显示自己的合成视图会阻止显示系统合成视图。当然是一个黑客,但它完成了任务


希望这能有所帮助。

我刚刚想出了一个解决这个问题的方法(在我的例子中,设置电子邮件的主题): 在内部,UIActivityViewController将在某个时间点调用MFMailComposeViewController类的setMessageBody:isHTML:方法,只需拦截该调用并在内部调用setSubject:方法。多亏了“方法旋转”技术,它看起来像:

#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
然后将自定义UIActivityItemProvider传递给UIActivityViewController,对于UIActivityTypeMail,它将返回HTML NSString,如:

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

邮件主题
正文
电子邮件的主题是从HTML标题中提取的(该部分使用纯文本,没有HTML实体或标记)


使用这种方法,我可以为您精心设计一种设置邮件收件人的优雅方法。

对于使用iOS6上的UIActivityViewController向电子邮件添加主题,这是任何人都可以使用的最佳解决方案。。您只需在初始化UIActivityViewController时调用以下命令

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

您的UIActivityViewController中填充了一个主题。

我不确定是否有收件人,但似乎在iOS 7及更高版本中,您可以通过遵循
UIActivityItemSource
协议并实现方法
activityViewController:subjectForActivityType:
来设置电子邮件的主题,因为大部分代码都是由Emanuelle编写的

虽然我想我会发布他的代码的修改版本,帮助设置收件人

我在MFMailComposeViewController上使用了一个类别

#import "MFMailComposeViewController+Recipient.h"
#import <objc/message.h>

@implementation MFMailComposeViewController (Recipient)

+ (void)load {
    MethodSwizzle(self, @selector(setMessageBody:isHTML:), @selector(setMessageBodySwizzled:isHTML:));
}



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);
    }
}

- (void)setMessageBodySwizzled:(NSString*)body isHTML:(BOOL)isHTML
{
    if (isHTML == YES) {
        NSRange range = [body rangeOfString:@"<torecipients>.*</torecipients>" options:NSRegularExpressionSearch|NSCaseInsensitiveSearch];
        if (range.location != NSNotFound) {
            NSScanner *scanner = [NSScanner scannerWithString:body];
            [scanner setScanLocation:range.location+14];
            NSString *recipientsString = [NSString string];
            if ([scanner scanUpToString:@"</torecipients>" intoString:&recipientsString] == YES) {
                NSArray * recipients = [recipientsString componentsSeparatedByString:@";"];
                [self setToRecipients:recipients];
            }
            body = [body stringByReplacingCharactersInRange:range withString:@""];
        }
    }
    [self setMessageBodySwizzled:body isHTML:isHTML];
}

@end
#导入“MFMailComposeViewController+Recipient.h”
#进口
@实现MFMailComposeViewController(收件人)
+(空)荷载{
方法swizzle(self,@selector(setMessageBody:isHTML:),@selector(setMessageBodySwizzled:isHTML:);
}
静态无效方法(c类、选择初始值、选择覆盖值)
{
方法origMethod=class_getInstanceMethod(c,origSEL);
方法overrideMethod=class_getInstanceMethod(c,overrideSEL);
if(class_addMethod(c,origSEL,method_getImplementation(overrideMethod),method_getTypeEncoding(overrideMethod))){
类_replaceMethod(c,overrideSEL,方法_getImplementation(origMethod),方法_getTypeEncoding(origMethod));
}否则{
方法交换实施(原始方法,替代方法);
}
}
-(void)setMessageBodySwizzled:(NSString*)body isHTML:(BOOL)isHTML
{
如果(isHTML==是){
nsrrange range=[body rangeOfString:@.*”选项:NSRegularExpressionSearch | NSCaseInsensitiveSearch];
if(range.location!=NSNotFound){
NSScanner*扫描仪=[NSScanner scannerWithString:body];
[扫描仪设置扫描位置:范围位置+14];
NSString*recipientsString=[NSString];
if([scanner scanuptString:@“intoString:&recipientsString]==是){
NSArray*recipients=[recipientsString组件由字符串分隔:@];“];
[自我设置收件人:收件人];
}
body=[body stringByReplacingCharactersInRange:range with string:@'';
}
}
[self-setMessageBodySwizzled:body-isHTML:isHTML];
}
@结束

谢谢你的建议。我已经尝试过了,mailto URL的内容刚刚添加到电子邮件的正文中。看来这不是解决办法
#import "MFMailComposeViewController+Recipient.h"
#import <objc/message.h>

@implementation MFMailComposeViewController (Recipient)

+ (void)load {
    MethodSwizzle(self, @selector(setMessageBody:isHTML:), @selector(setMessageBodySwizzled:isHTML:));
}



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);
    }
}

- (void)setMessageBodySwizzled:(NSString*)body isHTML:(BOOL)isHTML
{
    if (isHTML == YES) {
        NSRange range = [body rangeOfString:@"<torecipients>.*</torecipients>" options:NSRegularExpressionSearch|NSCaseInsensitiveSearch];
        if (range.location != NSNotFound) {
            NSScanner *scanner = [NSScanner scannerWithString:body];
            [scanner setScanLocation:range.location+14];
            NSString *recipientsString = [NSString string];
            if ([scanner scanUpToString:@"</torecipients>" intoString:&recipientsString] == YES) {
                NSArray * recipients = [recipientsString componentsSeparatedByString:@";"];
                [self setToRecipients:recipients];
            }
            body = [body stringByReplacingCharactersInRange:range withString:@""];
        }
    }
    [self setMessageBodySwizzled:body isHTML:isHTML];
}

@end