web-dev-qa-db-ja.com

iOS 6でUIActivityViewControllerの受信者を設定するにはどうすればよいですか?

IOS6の新しいUIActivityViewControllerクラスを使用して、ユーザーにさまざまな共有オプションを提供しています。テキスト、リンク、画像などのパラメータの配列を渡すことができ、それが残りを行います。

受信者を定義するにはどうすればよいですか?たとえば、メールまたはSMS=で共有すると、受信者を受け入れることができるはずですが、この動作を呼び出す方法がわかりません。

MFMessageComposeViewControllerUIActivityViewControllerを別々に使用する必要はありません。共有コントローラーの目的に反するためです。

助言がありますか?

IActivityViewControllerクラス参照

編集:これは送信されましたAppleその後、重複したバグレポートとマージされました。

OpenRadarのバグレポート

32
MattCheetham

ほとんどのコードを思いついたので、ここでのすべての功績はエマニュエルにあります。

を受信者に設定するのに役立つ彼のコードの修正版を投稿すると思いましたが。

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
3
thewormsterror

IOS6でUIActivityViewControllerを使用して電子メールにsubjectを追加する場合、これは誰でも使用できる最適なソリューションです。UIActivityViewControllerを初期化するときに次のコードを呼び出すだけです。

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

そして、UIActivityViewControllerにサブジェクトが入力されます。

24
Ajay

私はこの問題の解決策を思いついただけです(私の場合、電子メールの件名を設定します)。 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

UIActivityViewControllerを使用する前に、次のコード行を呼び出します。

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

次に、UIActivityViewControllerにカスタムUIActivityItemProviderを渡します。UIActivityTypeMailの場合、次のようなHTML NSStringを返します。

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

メールの件名はHTMLタイトルから抽出されます(その部分にはプレーンテキストを使用し、htmlエンティティやタグは使用しないでください)。

その方法を使用して、メールの受信者を設定するエレガントな方法を詳しく説明します。

10
Emmanuel Paris

現在のところメールの件名と本文を設定するmailto:ソリューションが機能していないようですが、HTMLを含むようにメールの本文を設定し、それでもAppleのシステムのメールアイコンを利用する場合、これは適切ではありません。 UIActivityViewControllerを介して。

それがまさに私たちがやりたかったことです。システムアイコンを使用しますが、電子メールには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;
    }
_

ステップ2:UIActivityViewControllerをサブクラス化し、次のようにMFMailComposeViewControllerDelegateにします。

_    @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;
    }
_

注:_super initWithActivityItems_を呼び出すときは、共有するオブジェクトをカスタムActivityItemSourceでラップします。

手順3:ユーザーがメールアイコンをタップしたときに、システムの代わりに独自のMFMailComposeViewControllerを起動します。

これは、ActivityItemSourceクラスのactivityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityTypeメソッドで行います。

_    - (id)activityViewController:(UIActivityViewController *)activityViewController                 itemForActivityType:(NSString *)activityType
    {
        if([activityType isEqualToString:UIActivityTypeMail]) {
                //TODO: fix; this is a hack; but we have to wait till Apple fixes the         inability to set subject and html body of email when using UIActivityViewController
                [self setEmailContent:activityViewController];
                return nil;
            }
         return self.object;
    }


    - (void) setEmailContent:(UIActivityViewController *)activityViewController 
    {

       MFMailComposeViewController *mailController = [ShareViewController mailComposeControllerWithObject: self.object withDelegate: activityViewController];

        [activityViewController presentViewController:mailController animated:YES completion:nil];

    }
_

mailComposeControllerWithObjectメソッドでは、MFMailComposeViewControllerクラスのインスタンスをインスタンス化し、必要なデータを含むように設定します。また、activityViewControllerを構成ビューのデリゲートとして設定することにも注意してください。

これが機能する理由は、コンポーズモーダルが表示されると、他のモーダルが表示されなくなるためです。つまり、独自のコンポーズビューを表示すると、システムコンポーズビューが表示されなくなります。間違いなくハックですが、仕事は完了です。

お役に立てれば。

8
ilyashev

受信者はわかりませんが、iOS 7以降では、UIActivityItemSourceプロトコルに準拠し、メソッドactivityViewController:subjectForActivityType:を実装することで、メールの件名を設定できるようです。

1
Tim Camber

NSUrlオブジェクトを使用して、mailto:スキーム(またはテキストメッセージの場合はsms :)で受信者を含めることができるはずです。

UIActivityクラスリファレンスから:

IActivityTypeMailオブジェクトは、提供されたコンテンツを新しい電子メールメッセージに投稿します。このサービスを使用する場合、NSStringオブジェクトとUIImageオブジェクト、およびローカルファイルを指すNSURLオブジェクトをアクティビティアイテムのデータとして提供できます。内容がmailtoスキームを使用するNSURLオブジェクトを指定することもできます。

したがって、次のようなものが機能するはずです。

NSString *text = @"My mail text";
NSURL *recipients = [NSURL URLWithString:@"mailto:[email protected]"];

NSArray *activityItems = @[text, recipients];

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

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