Subclass and using UIActivityItemProvider with UIActivityViewController - ios

I finally find someone who was facing the same problem than me.
UIActivityViewController customize text based on selected activity
I want to customize the content share with the activities of the UIActivityViewController. The good answer is the following:
"Instead of passing the text strings into the initWithActivityItems
call, pass in your own sub-class of the UIActivityItemProvider class
and when you implement the itemForActivityType method it will provide
the sharing service as the 'activityType' parameter.
You can then return the customized content from this method."
I understand tricks, but I'm not getting the way to do it...
I did this as a subclass:
#interface SharingItems : UIActivityItemProvider
#implementation SharingItems
-(id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
{
// Here depending on the activityType i want to share NSString or UIImage
}
#end
But I don't know what to do now in my original viewController:
-(void)actionSheet
{
if ([[UIActivityViewController class] respondsToSelector:#selector(alloc)])
{
__block NSString *imgName = [[NSString alloc] initWithFormat:#"%#", _sharingUrl];
NSArray *activityItems = [NSArray arrayWithObjects:imgName, nil];
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
[self presentViewController:activityController animated:YES completion:nil];
__block NSString *chan = [[NSString alloc] initWithFormat:#"%#", _channel];
[activityController setCompletionHandler:^(NSString* activityType, BOOL completed)
{
if (completed)
{
}
}];
}
else
[self displayActionSheet];
}

Here's an example UIActivityItemProvider (not tested but adapted from working code):
#implementation StringProvider
- (id)initWithPlaceholderString:(NSString*)placeholder facebookString:(NSString*)facebookString
{
self = [super initWithPlaceholderItem:placeholder];
if (self) {
_facebookString = facebookString;
}
return self;
}
- (id)item
{
if ([self.activityType isEqualToString:UIActivityTypePostToFacebook]) {
return _facebookString;
} else {
return self.placeholderItem;
}
}
#end
Then when you set up the activity view controller:
StringProvider *stringProvider = [[StringProvider alloc] initWithPlaceholderString:#"Default string" facebookString:#"Hello, Facebook."];
UIActivityViewController *shareController = [[UIActivityViewController alloc] initWithActivityItems:#[stringProvider] applicationActivities:nil];
Basically you create UIActivityItemProviders that provide the right data when the -(id)item method is called and pass in those activity item providers when you create the activity view controller. You need to initialize with a placeholder item so the OS knows what class the final item will be (most likely NSString, NSURL, UIImage). Hope that helps!

Related

How can share images, messages and urls in ios (objective-c)

Please Help us..
We want to share projects (i.e. Its Images, text and also my app url).
But i can't get SDK to share all on whatsApp, facebook, twitter, mails and messages. same as android developer using Intent called ACTION_SEND
Try this -
- (void)shareText:(NSString *)text andImage:(UIImage *)image andUrl:(NSURL *)url
{
NSMutableArray *sharingItems = [NSMutableArray new];
if (text) {
[sharingItems addObject:text];
}
if (image) {
[sharingItems addObject:image];
}
if (url) {
[sharingItems addObject:url];
}
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
[self presentViewController:activityController animated:YES completion:nil];
}
Call shareText like this -
[self shareText:#"Your text" andImage:nil andUrl:nil];

Unable to added Facebook and Twitter to UIActivityViewController

Trying to share application on social median, and email, and message.
Since Email and message is working fine for me.
But Facebook,and twitter is not all showing to UIActivityViewController
Below is code which i try.
NSArray *excludeActivities = #[UIActivityTypeAirDrop,
UIActivityTypePostToFacebook,
UIActivityTypePostToTwitter];
UIActivityViewController *activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:#[string, URL]
applicationActivities:nil];
activityViewController.excludedActivityTypes = excludeActivities;
[self presentViewController:activityViewController
animated:YES
completion:^{
}];
- (id)activityViewController:(UIActivityViewController *)activityViewController
itemForActivityType:(NSString *)activityType
{
if ([activityType isEqualToString:UIActivityTypePostToFacebook]) {
return NSLocalizedString(#"calling facebook", );
} else if ([activityType isEqualToString:UIActivityTypePostToTwitter]) {
return NSLocalizedString(#"calling twitter", );
} else {
return nil;
}
}
#All
Please let me know what i need to do.
For that just create one class for that like this.
SharingActivityProvider.h
#import <Foundation/Foundation.h>
#interface SharingActivityProvider : UIActivityItemProvider
#end
**SharingActivityProvider.m**
#import "SharingActivityProvider.h"
#implementation SharingActivityProvider {
}
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType {
// Create the default sharing string
NSString *shareString = #"";
// customize the sharing string for facebook, twitter, weibo, and google+
if ([activityType isEqualToString:UIActivityTypePostToFacebook]) {
shareString = [NSString stringWithFormat:#"Attention Facebook:%#", shareString];
} else if ([activityType isEqualToString:UIActivityTypePostToTwitter]) {
shareString = [NSString stringWithFormat:#"Attention Twitter:%#", shareString];
} else if ([activityType isEqualToString:UIActivityTypePostToWeibo]) {
shareString = [NSString stringWithFormat:#"Attention Weibo:%#", shareString];
}
return shareString;
}
- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController {
return #"";
}
#end
Then after just use below code, suppose button action.
-(IBAction)shareAppTapped:(id)sender{
SharingActivityProvider *sharingActivityProvider = [[SharingActivityProvider alloc] init];
NSArray *activityProviders = #[sharingActivityProvider,#"what ever text"];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityProviders applicationActivities:nil];
// tell the activity view controller which activities should NOT appear
activityViewController.excludedActivityTypes = #[UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll];
activityViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:activityViewController animated:YES completion:nil];
// [self.btnShareApp setBackgroundColor:OnebackgroundColorTable];
}
One mistake here is exclude activities also have facebook and twitter. Hence it will not show by any means.
Note excludedActivityTypes should be which you does not need in controller.
For example it should be:
NSArray *excludeActivities = #[UIActivityTypePostToWeibo,
UIActivityTypeMessage,
UIActivityTypeAssignToContact,
UIActivityTypeSaveToCameraRoll,
UIActivityTypeAddToReadingList,
UIActivityTypePostToFlickr,
UIActivityTypePostToVimeo,
UIActivityTypePostToTencentWeibo];

UIDocumentInteractionController delegate method do not called when pressed on mail button

I want to show the Alert message When no mail is configured on the device.But when i click Mail from document interaction it just simply dismiss the controller none of the two following Delegate method will call.Please refer Image for better understanding.
Please help. Thanks in Advance
- (void)openAppList:(FileInfo *)fileinfo {
NSURL *fileURL = [NSURL fileURLWithPath:fileinfo.fullName];
UIDocumentInteractionController *interactionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
[interactionController retain];
interactionController.delegate = self;
BOOL present = [interactionController presentOptionsMenuFromRect:CGRectZero inView:self.tabBarController.view animated:YES];
if (!present) {
[MainteOrErrorDialog initWithErrorCode:kAlertNotOpenInFileId filename:fileInfo.filename target:nil action:nil];
} else {
[interactionController retain];
}
}
#pragma UIDocumentInteractionDelegate
- (void)documentInteractionController:(UIDocumentInteractionController *)controller
willBeginSendingToApplication:(NSString *)application
{
}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller
didEndSendingToApplication:(NSString *)application
{
}
Unfortunately, you can't really interact with the Mail delegates through UIDocumentInteractionController. UIDocumentInteractionController is extremely limited to what you can do with properties and attributes of all apps it supports, you can't even set a mails message body to a custom message. In fact, documentInteractionController:canPerformAction: is deprecated in iOS 6.0 because Apple was moving towards UIActivityViewController. They're own deprecated statement is :
Apps should use UIActivityViewController for actions
So alternatively, with UIActivityViewController you can.
A work around for this, implement UIActivityViewController, they both support the same apps and check if a user can send emails, if not, exclude Mail from the menu :
if ([MFMailComposeViewController canSendMail]) {
NSArray *shareItems;
shareItems = #[[Config emailMessage], snapshot]; //emailMessage is an NSString containing the body of the mail or mms message located in a different VC
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:shareItems applicationActivities:nil];
[activityController setCompletionWithItemsHandler:(UIActivityViewControllerCompletionWithItemsHandler)^(NSString *string, BOOL completed) {
}
[self presentViewController:activityController animated:YES completion:nil];
} else {
NSArray *shareItems;
shareItems = #[[Config emailMessage], snapshot]; //emailMessage is an NSString containing the body of the mail or mms message located in a different VC
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:shareItems applicationActivities:nil];
activityController.excludedActivityTypes = #[UIActivityTypeMail];
[activityController setCompletionWithItemsHandler:(UIActivityViewControllerCompletionWithItemsHandler)^(NSString *string, BOOL completed) {
}
[self presentViewController:activityController animated:YES completion:nil];
}

How do I use UIActivityItemProvider to send an email with attachment with UIActivityViewController?

I am trying to use UIActivityItemProvider to share a file from within my app via email attachment. I also need to populate the subject line of the email and to specify the name of the attachment to be something different than the name of the file stored on the device.
Here is the code that I'm using. The problem is that the attachment is missing from the email.
#interface ItemProvider:UIActivityItemProvider
#property (nonatomic, strong) NSURL *filepath;
#property (nonatomic, strong) NSString *emailBody;
#property (nonatomic, strong) NSString *emailSubject;
#end
#implementation ItemProvider
- (id)initWithPlaceholderItem:(id)placeholderItem
{
//Initializes and returns a provider object with the specified placeholder data
return [super initWithPlaceholderItem:placeholderItem];
}
- (id)item
{
//Generates and returns the actual data object
return [NSDictionary dictionary];
}
// The following are two methods in the UIActivityItemSource Protocol
// (UIActivityItemProvider conforms to this protocol) - both methods required
#pragma mark UIActivityItemSource
//- Returns the data object to be acted upon. (required)
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
{
if ([activityType isEqualToString:UIActivityTypeMail]) {
return #{#"body":self.emailBody, #"url":self.filepath};
}
return #{#"body":self.emailBody, #"url":self.filepath};
}
//- Returns the placeholder object for the data. (required)
//- The class of this object must match the class of the object you return from the above method
- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{
return #{#"body":self.emailBody, #"url":self.filepath};
}
-(NSString *) activityViewController:(UIActivityViewController *)activityViewController subjectForActivityType:(NSString *)activityType {
return self.emailSubject;
}
#end
And then in my viewController I do this:
ItemProvider *provider = [[ItemProvider alloc] initWithPlaceholderItem:#{#"body":emailBody, #"url":filePath}];
provider.emailBody = emailBody;
provider.emailSubject = info.title;
provider.filepath = filePath;
NSArray *activityItems = #[provider];
// Build a collection of custom activities (if you have any)
// NSMutableArray *customActivities = [[NSMutableArray alloc] init];
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
[self presentViewController:activityController animated:YES completion:nil];
For those still stumbling upon a solution for this, there is a more elegant solution for customizing UIActivityViewController. To address the original question, the reason the attachment is not showing up is because it is supposed to be a separate UIActivityItemProvider object.
So the solution is to create two UIActivityItemProvider subclasses, one to wrap the 'emailBody' and 'emailSubject' and another to wrap the attachment. The benefit to using a UIActivityItemProvider for the attachment is that you have the opportunity to delay processing the attachment until it is needed, rather than doing so before presenting UIActivityViewController.
Implement the AttachmentProvider class to provide the attachment like so:
#implementation AttachmentProvider : UIActivityItemProvider
- (id)item {
if ([self.activityType isEqualToString:UIActivityTypeMail]) {
/* Replace with actual URL to a file. Alternatively
* you can also return a UIImage.
*/
return [NSData dataWithContentsOfURL:dataURL];
}
return nil;
}
#end
Implement EmailInfoProvider class to provider the email body and subject class like so:
#implementation EmailInfoProvider : UIActivityItemProvider
- (id)item {
return #"Your email body goes here";
}
- (NSString *)activityViewController:(UIActivityViewController *)activityViewController subjectForActivityType:(NSString *)activityType {
if ([activityType isEqualToString:UIActivityTypeMail]) {
return #"Your subject goes here";
}
return nil;
}
#end
You can then create a UIActivityViewController with both these items in your viewController like so:
- (void)shareAction {
AttachmentProvider *attachment = [[AttachmentProvider alloc] init];
EmailInfoProvider *emailContent = [[EmailInfoProvider alloc] init];
// You can provider custom -(id)init methods to populate EmailInfoProvider
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:#[attachment, emailContent] applicationActivities:nil];
[self presentViewController:activityController animated:YES completion:nil];
}
i'm sending email with attachment without ItemProvider. its working well :-)
NSMutableArray *selDocs = [[NSMutableArray alloc] init];
for (Document *theDoc in self.selectedDocs) {
NSURL *fileUrl = [NSURL fileURLWithPath:theDoc.filePath];
[selDocs addObject:fileUrl];
}
NSArray *postItems = [NSArray arrayWithArray:selDocs];
UIActivityViewController *avc = [[UIActivityViewController alloc] initWithActivityItems:postItems applicationActivities:nil];
[avc setValue:#"Your email Subject" forKey:#"subject"];
avc.completionHandler = ^(NSString *activityType, BOOL completed){
NSLog(#"Activity Type selected: %#", activityType);
if (completed) {
NSLog(#"Selected activity was performed.");
} else {
if (activityType == NULL) {
NSLog(#"User dismissed the view controller without making a selection.");
} else {
NSLog(#"Activity was not performed.");
}
}
};
[self presentViewController:avc animated:YES completion:nil];

Default Sharing in iOS 7

I have seen this format (Image shown below) of share option in most of the iOS applications that support iOS 7.
Is there a default code/framework available to implement this share option as it is shown in the image below?
What you are looking for is the UIActivityViewController.
Since you asked a general question I can't do more than give you a link to the documentation
In addition to the accepted answer, a small piece of example code
- (void)shareText:(NSString *)text andImage:(UIImage *)image andUrl:(NSURL *)url
{
NSMutableArray *sharingItems = [NSMutableArray new];
if (text) {
[sharingItems addObject:text];
}
if (image) {
[sharingItems addObject:image];
}
if (url) {
[sharingItems addObject:url];
}
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
[self presentViewController:activityController animated:YES completion:nil];
}
Call shareText, leave the things that you don't want to share at nil.
[self shareText:#"Hello world" andImage:nil andUrl:nil];
The Controller in the image you posted is the UIActivitiyViewController this is a link to the class documentation
some good example code:
How to display the default iOS 6 share action sheet with available share options?
I know this question is particular to iOS 7, and the code example specifies iOS 6, but AFAICT they are very similar one might find the example code as helpful as I did.
UIActivityViewController is what you are looking for.
You can specify either the items or the applications
UIActivityViewController *actCont = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
Just use following code for Default Sharing. You can able to add more items into shareItems array as per your requirement.
NSMutableArray *shareItems = [[NSMutableArray alloc] initWithObjects:
#"Hello",
[UIImage imageNamed:#"your_image.png"],
#"http://google.com/", nil];
[self shareItemToOtherApp:shareItems];
Following method is for default sharing Text or Image into other Apps:-
-(void)shareItemToOtherApp:(NSMutableArray *)shareItems{
UIActivityViewController *shareController = [[UIActivityViewController alloc]
initWithActivityItems: shareItems applicationActivities :nil];
[shareController setValue:#"Sharing" forKey:#"subject"];
shareController.excludedActivityTypes = #[UIActivityTypePostToWeibo, UIActivityTypeAssignToContact, UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeSaveToCameraRoll];
shareController.completionHandler = ^(NSString *activityType, BOOL completed)
{
//NSLog(#" activityType: %#", activityType);
//NSLog(#" completed: %i", completed);
};
[self presentViewController: shareController animated: YES completion: nil];
}
If you want to make Custom Sharing sheet then use following code. For this, you have to import <Social/Social.h> framework.
-(void)shareOnFacebook:(id)sender {
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook])
{
SLComposeViewController *faceSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
// NSLog(#"%#", messageField.text);//This returns the appropriate string
[faceSheet setInitialText:#"Hellooooooo"];
//The facebook VC appears, but initial text is not set to messageField.text
[self presentViewController:faceSheet animated:YES completion:nil];
}
else
{
NSLog(#"Please first install Application and login in Facebook");
}
}
-(void)shareOnTwitter:(id)sender {
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
[tweetSheet setInitialText:#"Hello"];
[self presentViewController:tweetSheet animated:YES completion:nil];
}
else{
NSLog(#"Please first install Application and login in Twitter");
}
}
Hope, this is what you're looking for. Any concern get back to me. :)

Resources