Как установить получателей для UIActivityViewController в iOS 6?

Я использую новый class UIActivityViewController в iOS6, чтобы предоставить пользователю различные параметры совместного доступа. Вы можете передать массив параметров, таких как текст, ссылки и изображения, и все остальное.

Как определить получателей? Например, обмен сообщениями по почте или SMS должен иметь возможность принимать получателей, но я не могу понять, как вызвать это поведение.

Я не хочу, чтобы вам приходилось использовать MFMessageComposeViewController и UIActivityViewController отдельно, поскольку это просто побеждает цель controllerа MFMessageComposeViewController UIActivityViewController .

Какие-либо предложения?

Ссылка на class UIActivityViewController

Изменить: теперь он был отправлен Apple и впоследствии объединен с дублированным отчетом об ошибке.

Отчет об ошибках в OpenRadar

Весь кредит здесь относится к Emanuelle, так как он придумал большую часть кода.

Хотя я думал, что опубликую модифицированную версию его кода, которая поможет установить получателя.

Я использовал Категория на MFMailComposeViewController

 #import "MFMailComposeViewController+Recipient.h" #import  @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:@".*" options:NSRegularExpressionSearch|NSCaseInsensitiveSearch]; if (range.location != NSNotFound) { NSScanner *scanner = [NSScanner scannerWithString:body]; [scanner setScanLocation:range.location+14]; NSString *recipientsString = [NSString string]; if ([scanner scanUpToString:@"" intoString:&recipientsString] == YES) { NSArray * recipients = [recipientsString componentsSeparatedByString:@";"]; [self setToRecipients:recipients]; } body = [body stringByReplacingCharactersInRange:range withString:@""]; } } [self setMessageBodySwizzled:body isHTML:isHTML]; } @end 

Чтобы добавить тему с помощью UIActivityViewController на iOS6, это лучшее решение, которое может использовать любой пользователь. Все, что вам нужно сделать, это вызвать следующее при инициализации UIActivityViewController.

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

И ваш UIActivityViewController заполнен субъектом.

Я просто придумал решение этой проблемы (в моем случае задал вопрос по электронной почте): так как внутренне UIActivityViewController вызовет в какой-то момент метод setMessageBody: isHTML: class MFMailComposeViewController, просто перехватите этот вызов и внутри сделайте вызов метода setSubject:. Благодаря методу «swizzling» метода это выглядит так:

 #import  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:@".*" options:NSRegularExpressionSearch|NSCaseInsensitiveSearch]; if (range.location != NSNotFound) { NSScanner *scanner = [NSScanner scannerWithString:body]; [scanner setScanLocation:range.location+7]; NSString *subject = [NSString string]; if ([scanner scanUpToString:@"" 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, например:

  Subject of the mail  Body of the mail  

Тема электронной почты извлекается из заголовка HTML (используйте обычный текст для этой части, никаких объектов или тегов html).

Используя этот метод, я расскажу вам об элегантном способе настройки получателя почты.

Хотя кажется, что в настоящее время mailto: решение для настройки темы и тела электронной почты не работает, это ни в коем случае не будет адекватным, если вы хотите, чтобы тело электронной почты содержало HTML и по-прежнему использовало значок электронной почты системы Apple через UIActivityViewController.

Это именно то, что мы хотели сделать: используйте значок системы, но в письме есть тело HTML и пользовательский объект.

Наше решение было чем-то вроде взлома, но оно работает хорошо, по крайней мере на данный момент. Это связано с использованием MFMailComposeViewController, но он по-прежнему позволяет использовать значок системной почты с помощью UIActivityViewController.

Шаг 1. Создайте class оболочки, соответствующий источнику UIActivityItem, например:

  @interface ActivityItemSource : NSObject  @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: Подclass UIActivityViewController и превратите его в MFMailComposeViewControllerDelegate следующим образом:

  @interface ActivityViewController : UIActivityViewController  @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 вместо системного, когда пользователь нажимает на значок Mail.

Это можно сделать в activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType в classе ActivityItemSource:

  - (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 вы создаете экземпляр classа MFMailComposeViewController и устанавливаете его для хранения любых необходимых данных. Также обратите внимание, что вы должны установить ActivityViewController в качестве делегата представления представления.

Причина этого заключается в том, что при отображении мода модаса это предотвращает отображение других модалов, т. Е. Вы показываете свое собственное представление компоновки, из которого система отображает представление. Определенно, взлом, но он выполняет свою работу.

Надеюсь это поможет.

Вы должны иметь возможность включать получателей, используя объект NSUrl, с помощью схемы mailto: (или sms: для текстовых сообщений).

Из ссылки classа UIActivity:

UIActivityTypeMail Объект помещает предоставленный контент в новое сообщение электронной почты. При использовании этой службы вы можете предоставить объекты NSString и UIImage и объекты NSURL, указывающие на локальные файлы в качестве данных для элементов активности. Вы также можете указать объекты NSURL, содержимое которых использует схему mailto.

Поэтому что-то вроде этого должно работать:

 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]; 

Я не уверен в получателях, но похоже, что в iOS 7 и более поздних версиях вы можете задать тему электронной почты в соответствии с протоколом UIActivityItemSource и реализовать метод activityViewController:subjectForActivityType:

  • UIButton внутри представления с UITapGestureRecognizer
  • objective-C - Когда использовать «я»,
  • Как написать данные в plist?
  • Сортировка NSArray строк или объектов даты
  • Как программно изменить оттенок UIImage?
  • Центральное содержимое UIScrollView при меньшем
  • UITableViewCell расширяется по клику
  • Поиск NSArray для значения соответствия значений
  • Содержимое HTML соответствует UIWebview без масштабирования
  • Как размыть сцену в SpriteKit?
  • Остановить UIWebView от «подпрыгивания» по вертикали?
  • Давайте будем гением компьютера.