IOS6の新しいUIActivityViewController
クラスを使用して、ユーザーにさまざまな共有オプションを提供しています。テキスト、リンク、画像などのパラメータの配列を渡すことができ、それが残りを行います。
受信者を定義するにはどうすればよいですか?たとえば、メールまたはSMS=で共有すると、受信者を受け入れることができるはずですが、この動作を呼び出す方法がわかりません。
MFMessageComposeViewController
とUIActivityViewController
を別々に使用する必要はありません。共有コントローラーの目的に反するためです。
助言がありますか?
編集:これは送信されましたAppleその後、重複したバグレポートとマージされました。
ほとんどのコードを思いついたので、ここでのすべての功績はエマニュエルにあります。
を受信者に設定するのに役立つ彼のコードの修正版を投稿すると思いましたが。
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
IOS6でUIActivityViewControllerを使用して電子メールにsubjectを追加する場合、これは誰でも使用できる最適なソリューションです。UIActivityViewControllerを初期化するときに次のコードを呼び出すだけです。
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities];
[activityViewController setValue:@"My Subject Text" forKey:@"subject"];
そして、UIActivityViewControllerにサブジェクトが入力されます。
私はこの問題の解決策を思いついただけです(私の場合、電子メールの件名を設定します)。 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エンティティやタグは使用しないでください)。
その方法を使用して、メールの受信者を設定するエレガントな方法を詳しく説明します。
現在のところメールの件名と本文を設定する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
を構成ビューのデリゲートとして設定することにも注意してください。
これが機能する理由は、コンポーズモーダルが表示されると、他のモーダルが表示されなくなるためです。つまり、独自のコンポーズビューを表示すると、システムコンポーズビューが表示されなくなります。間違いなくハックですが、仕事は完了です。
お役に立てれば。
受信者はわかりませんが、iOS 7以降では、UIActivityItemSource
プロトコルに準拠し、メソッドactivityViewController:subjectForActivityType:
を実装することで、メールの件名を設定できるようです。
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];