UIActivityViewController not passing new line characters to some activities - ios

I am using the following code to set up UIActivityViewController:
NSArray *activityItems = [NSArray arrayWithObjects:[self textMessageToShare], nil];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed) {
if (completed) {
[self sendFeedbackWithIndexPath:indexPath AndLikeType:100 AndCell:nil];
}
}];
[self.navigationController presentViewController:activityViewController
animated:YES
completion:^{
// ...
}];
Issue is that when I copy a message or post to facebook or twitter or email or gmail app or to default Messages app, the new line characters that are in [self textMessageToShare] are maintained. However, if I share to other activities like WhatsApp or Viber - all the new line characters are removed, and the whole message is sent as one single line.
Whereas, if I share just text through iOS default Notes app, new line characters are maintained when shared to these apps. How would the Notes app be storing the new line characters? I am using \n as the new line character.
For my life unable to even find the reason. Can anyone help?

I was able to make it work by converting the newline characters to "<br/>":
_myDataString= self.textview.text;
_myDataString= [_myDataString stringByReplacingOccurrencesOfString:#"\n" withString:#"<br/>"];

Please check the new line issue in whats app share using uiactivityviewcontroller.
#import <UIKit/UIKit.h>
#interface ShareActivity : UIActivityItemProvider
#property (nonatomic, strong) NSString *message;
#property (nonatomic, strong) NSArray *activities;
#end
#import "ShareActivity.h"
#implementation ShareActivity
#synthesize message = _message;
#synthesize activities = _activities;
- (id) activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
{
if([activityType isEqualToString:#"net.whatsapp.WhatsApp.ShareExtension"])
{
return [self.message stringByReplacingOccurrencesOfString:#"\n" withString:#"<br/>"];
}
else if ([self.activities containsObject:activityType])
{
return [self.message stringByReplacingOccurrencesOfString:#"\n" withString:#"<br/>"];
}
else
{
return self.message;
}
return nil;
}
- (id) activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{
return #"";
}
In View Controller Class on any action button to pop up the share view
Apply this action on any button action
-(void)shareAction
{
ShareActivity *shareObj = [[ShareActivity alloc] initWithPlaceholderItem:#""];
NSString *message = #"New\nLine\nText\nMessage";
[shareObj setMessage:message];
NSArray* dataToShare = #[shareObj];
NSArray *excludeActivities = #[UIActivityTypePrint,UIActivityTypeOpenInIBooks,UIActivityTypeAddToReadingList,UIActivityTypePostToTencentWeibo,UIActivityTypeSaveToCameraRoll,UIActivityTypeAirDrop];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:dataToShare applicationActivities:nil];
activityVC.excludedActivityTypes = excludeActivities;
[activityVC setCompletionHandler:^(NSString *act, BOOL done)
{
NSString *ServiceMsg = nil;
if ( [act isEqualToString:UIActivityTypeMail] )
{
ServiceMsg = #"Mail sent!";
}
else if ( [act isEqualToString:UIActivityTypePostToTwitter] )
{
ServiceMsg = #"Post on twitter, ok!";
}
else if ( [act isEqualToString:UIActivityTypePostToFacebook] )
{
ServiceMsg = #"Post on facebook, ok!";
}
else if ( [act isEqualToString:UIActivityTypeCopyToPasteboard] )
{
ServiceMsg = #"Message copy to pasteboard";
}
else if ( [act isEqualToString:UIActivityTypePostToFlickr] )
{
ServiceMsg = #"Message sent to flickr";
}
else if ( [act isEqualToString:UIActivityTypePostToVimeo] )
{
ServiceMsg = #"Message sent to Vimeo";
}
else
{
}
}];
[self presentViewController:activityVC animated:YES completion:nil];
}

hi its me again i was looking for the right answer
and i found that you can do it by using a Custom Share Message to Different Providers .
and you can find an example from this Code check for MyActivityItemProvider class .
https://github.com/apascual/flip-your-phone
i hove a problem posting the code here so i think the link above will help

Thanks to MuslimDev2015 I have been able to develop a solution:
https://github.com/lorenzoPrimi/NewlineActivityItemProvider
Try it and let me know.

You can send the text as multiple items each item is just one line.
let lines = text.components(separatedBy: "\n")
let activityViewController = UIActivityViewController(activityItems: lines, applicationActivities: nil)

Related

SMS behavior using UIActivityViewController

I'm using a UIActivityViewController to share some text from within my app. I've subclassed the UIActivityItemProvider so that I can handle the text depending on the sharing application selected. Before I present the view controller, I create a text file that can get attached to a mail message. (I write the file to a URL and add it to the shared items array.) If the user taps the Mail icon, the text document file gets attached to the message and all is good in the world. Here is the code I use:
- (IBAction)shareBarButtonPressed:(UIBarButtonItem *)sender
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
NSString *resultsFile = [docPath stringByAppendingString:#"/results.txt"];
[self createResultFile];
NSURL *fileUrl = [NSURL fileURLWithPath:resultsFile];
NSData *fileData = [[NSData alloc]initWithContentsOfFile:resultsFile];
[fileData writeToURL:fileUrl atomically:YES];
NSString *testString = #"This is my string";
PRActivityProvider *activityProvider = [[PRActivityProvider alloc] initWithPlaceholderItem:[self fillResultFromView]];
NSArray *items = #[activityProvider, testString];
UIActivityViewController *activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:items
applicationActivities:nil];
NSString *subject = [NSString stringWithFormat:#"Results: %#",self.result.eventName];
[activityViewController setValue:subject forKey:#"subject"];
[activityViewController setExcludedActivityTypes:
#[UIActivityTypeSaveToCameraRoll,
UIActivityTypeAssignToContact,
UIActivityTypePostToTencentWeibo,
UIActivityTypeCopyToPasteboard]];
[self presentViewController:activityViewController animated:YES completion:nil];
[activityViewController setCompletionHandler:^(NSString *act, BOOL done)
{
NSString *ServiceMsg = nil;
if ( [act isEqualToString:UIActivityTypeMail] ) ServiceMsg = #"Results sent!";
if ( [act isEqualToString:UIActivityTypePostToTwitter] ) ServiceMsg = #"Results posted on Twitter!";
if ( [act isEqualToString:UIActivityTypePostToFacebook] ) ServiceMsg = #"Results posted on FaceBook!";
if ( [act isEqualToString:UIActivityTypeMessage] ) ServiceMsg = #"SMS sent!";
if ( done )
{
UIAlertView *Alert = [[UIAlertView alloc] initWithTitle:ServiceMsg message:#"" delegate:nil cancelButtonTitle:#"ok" otherButtonTitles:nil];
[Alert show];
}
}];
However, I have two problems:
First, when the user taps the SMS icon to send the NSString in a text, the file that got created earlier also gets attached (or imbedded) in the text of the message. Is there a way to 'selectively' attach a file depending on which sharing service is selected? Or maybe a way to remove the file when the user taps the SMS icon? Is there some housekeeping that I need to do in the activity provider subclass to clean up the text message?
Second, on a real device the SMS message doesn't get to its target. The completion handler triggers and shows the SMS message completes, but I never receive it. Not sure there is a race condition here or not - it actually worked once where I received the text message with the string.
Here is the activityController code:
- (id) activityViewController:(UIActivityViewController *)activityViewController
itemForActivityType:(NSString *)activityType
// the number of item to share
static UIActivityViewController *shareController;
static int itemNo;
if (shareController == activityViewController && itemNo < numberOfSharedItems - 1)
itemNo++;
else {
itemNo = 0;
shareController = activityViewController;
}
PRResults *result = [[PRResults alloc]init];
result = self.placeholderItem;
// twitter
if ([activityType isEqualToString: UIActivityTypePostToTwitter]) {
return [self makeTweetFromResult:result];
}
// SMS text message
else if ([activityType isEqualToString: UIActivityTypeMessage]) {
return [self makeTweetFromResult:result];
}
// email
else if ([activityType isEqualToString: UIActivityTypeMail]) {
return #"Open the attached results file in a notepad app to view.";
}
// Facebook
else if ([activityType isEqualToString:UIActivityTypePostToFacebook]) {
return [self makeFacebookPostFromResult:result];
}
return nil;

UIDocumentInteractionController not showing print option

I have code to show a document as follows:
documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:self.thisUrl];
NSString *pathExtension = [self.thisUrl pathExtension];
if (pathExtension) {
NSString *UTI = (__bridge NSString*)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)(pathExtension), NULL);
if (UTI) {
documentInteractionController.UTI = UTI;
}
}
documentInteractionController.delegate = self;
[documentInteractionController presentOptionsMenuFromBarButtonItem:shareButton animated:YES];
When the options menu is displayed, it shows a list of apps that can open the document (e.g. Message), along with a list of actions below.
The options menu shows a list actions that is different from the menu shown in e.g., the Mail app.
The main difference is that the Mail app shows a "print" option, while my options menu does not. How do I get the options menu to show the print option?
EDIT:
I did a further test where I implemented the methods:
- (BOOL)documentInteractionController:(UIDocumentInteractionController *)controller canPerformAction:(SEL)action
{
return YES;
}
- (BOOL)documentInteractionController:(UIDocumentInteractionController *)controller performAction:(SEL)action
{
return YES; // or NO, doesn't matter
}
This had the effect of showing the "print", "copy" and "save to camera roll" actions in the popup view. Nothing happened when I tapped them, probably because I didn't properly implement -performAction. I also get a warning in the console log about using legacy methods.
This was a step backwards in some ways because I could no longer print some documents which were able to print correctly with the document interaction controller before I added those methods.
Apple encourage you to use UIActivityViewController. You can easily achieve this with that. However Print option is available only if your sharing content type supports printing. You can see a list of supported activities by data types here
- (IBAction)shareButton:(UIBarButtonItem *)sender
{
NSString *textToShare = #"Text to share";
NSURL *myWebContent = [NSURL URLWithString:#"http://yourpath.com/yourfile.pdf"]; // set your printable file here!
NSData *myData = [NSData dataWithContentsOfURL:myWebContent];
NSArray *objectsToShare = #[textToShare, myData];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:objectsToShare applicationActivities:nil];
//Add exclusions here
NSArray *excludeActivities = #[UIActivityTypeAirDrop,
UIActivityTypeAssignToContact,
UIActivityTypeSaveToCameraRoll,
UIActivityTypeAddToReadingList,
UIActivityTypePostToFlickr,
UIActivityTypePostToVimeo];
activityVC.excludedActivityTypes = excludeActivities;
[self presentViewController:activityVC animated:YES completion:nil];
}
I got this working using the QuickLook framework. I don't know why the "print" option sometimes doesn't appear for the document interaction controller, but then again, apparantly noone else does either.
The QuickLook framework supports previewing some document types but not all, so I left in my previous view controller and the document interaction controller for those unsupported types.
Below is a snippet of my working code.
#interface PreviewItemDataSource ()
#property (nonatomic, retain) NSURL* item;
#end
#implementation PreviewItemDataSource
#synthesize item=_item;
+(PreviewItemDataSource*)dataSourceWithItem:(NSURL*)item
{
PreviewItemDataSource *source = [[PreviewItemDataSource alloc] init];
source.item = item;
return source;
}
-(NSInteger) numberOfPreviewItemsInPreviewController:(QLPreviewController*)controller {
return 1;
}
- (id<QLPreviewItem>) previewController:(QLPreviewController*)controller previewItemAtIndex:(NSInteger)index {
return self.item;
}
#end
#interface AppDelegate ()
#property (nonatomic, retain) PreviewItemDataSource *dataSource;
#end
...
-(void) openExternalFile:(NSString*) filePath withDelegate:(id<ChildBrowserDelegate>)delegate
{
if ([filePath length] == 0)
return;
NSURL *item = [NSURL URLWithString:filePath];
if (item && [QLPreviewController canPreviewItem:item]) {
[self openQuickLookForItem:item];
} else {
// previous method unchanged
}
}
- (void) openQuickLookForItem:(NSURL*)item {
QLPreviewController *controller = [[QLPreviewController alloc] init];
PreviewItemDataSource *dataSource = [PreviewItemDataSource dataSourceWithItem:item];
controller.dataSource = dataSource;
controller.modalPresentationStyle = UIModalPresentationFullScreen;
[controller setCurrentPreviewItemIndex:0];
[self.viewController presentViewController:controller animated:YES completion:nil];
self.dataSource = dataSource;
}

UIActivityViewController to post different image and text for Twitter and Facebook

In my project,I am using UIActivityViewController to do Facebook,Twitter and email sharing.I want to share separate text and images for facebook,Email and twitter.How can i do that?
-(id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
{
if ( [activityType isEqualToString:UIActivityTypePostToTwitter] )
return _shareText1;
if ( [activityType isEqualToString:UIActivityTypePostToFacebook] )
return _shareText2;
if ( [activityType isEqualToString:UIActivityTypeMail] )
return _shareText3;
return nil;
}
I used the above code in the subclass of UIActivityItemProvider,and passed the text to be shared from my UIViewcontroller.How to return an image with the text?Is it by returning a NSDictionary?If so,What are the keys?Please Help.
The best way you can create the UIActivity Subclass and use in UIActivityViewController..
-(void)sharePressed:(id)sender
{
GooglePlus *gPlus = [[GooglePlus alloc]init];
FacebookShare *fb =[[FacebookShare alloc]init];
NSString *textToShare = #"Text u want to share";
NSURL *myWebsite = [NSURL URLWithString:#"http://www.mywebsite.com/"];
UIImage *image =[UIImage imageNamed:#"apple.png"];
}
NSArray *objectsToShare = #[textToShare, myWebsite,image];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:objectsToShare applicationActivities:
[NSArray arrayWithObjects:gPlus,fb,nil]];
activityVC.completionHandler = ^(NSString *activityType, BOOL completed)
{
// NSLog(#" activityType: %#", activityType);
// NSLog(#" completed: %i", completed);
};
NSArray *excludedActivities = #[UIActivityTypePostToTwitter,
UIActivityTypePostToWeibo,
UIActivityTypeMessage,
UIActivityTypePrint, UIActivityTypeCopyToPasteboard,
UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll,
UIActivityTypeAddToReadingList, UIActivityTypePostToFlickr,
UIActivityTypePostToVimeo, UIActivityTypePostToTencentWeibo,UIActivityTypePostToFacebook];
activityVC.excludedActivityTypes = excludedActivities;
[self presentViewController:activityVC animated:YES completion:nil];
// Create the subclass the UIActivity Class using delegates
-(NSString *)activityType
{
return #"GooglePlus";
//CustomActivity
}
-(NSString *)activityTitle
{
return #"GooglePlus ";
// use your custom ActivityTitle
}
-(UIImage *)_activityImage
{
// Note: These images need to have a transparent background and I recommend these sizes:
// iPadShare#2x should be 126 px, iPadShare should be 53 px, iPhoneShare#2x should be 100
// px, and iPhoneShare should be 50 px. I found these sizes to work for what I was making.
return [UIImage imageNamed:#"G+-60x60.png"];
}
-(BOOL)canPerformWithActivityItems:(NSArray *)activityItems
{
NSLog(#"%s", __FUNCTION__);
return YES;
}
-(void)prepareWithActivityItems:(NSArray *)activityItems
{
NSLog(#"%s",__FUNCTION__);
}
-(UIViewController *)activityViewCtroller
{
NSLog(#"%s",__FUNCTION__);
return nil;
}
-(void)performActivity
{
// share what stuff u want to share
}

UIActivityViewController issue iOS 7 and iOS 8?

I’m building an article reading app for iPad. I have integrated a social sharing functionality which means user can share articles on Facebook, and google mail.
I’m using UIActivityViewController for sharing.
There is a bar button item,when user click on that UIActivityViewController opens.I updated Xcode 6
When I run on simulator it runs fine But I run on real device(iPad) with iOS 7,the app get crash on clicking on bar button item.
this is my code:
- (IBAction)ysshareAction:(id)sender
{
NSURL *linkURL = [NSURL URLWithString:_DetailModal1[4]];//article url
NSMutableAttributedString *stringText = [[NSMutableAttributedString alloc] initWithString:_DetailModal1[0]];//_DetailModal1[0] contain article title////
[stringText addAttribute:NSLinkAttributeName value:linkURL range:NSMakeRange(0, stringText.length)];
NSArray * itemsArray = #[[NSString stringWithFormat:#"%#",_DetailModal1[0]], [NSURL URLWithString:_DetailModal1[4]]];
NSArray * applicationActivities = nil;
UIActivityViewController * AVC = [[UIActivityViewController alloc] initWithActivityItems:itemsArray applicationActivities:applicationActivities];
AVC.popoverPresentationController.sourceView = _webView;
[self presentViewController:AVC animated:YES completion:nil];
[AVC setCompletionHandler:^(NSString *act, BOOL done)
{
if([act isEqualToString:UIActivityTypeMail]) {
ServiceMsg = #"Mail sent!";
} else if([act isEqualToString:UIActivityTypePostToTwitter]) {
ServiceMsg = #"Article Shared!";
} else if([act isEqualToString:UIActivityTypePostToFacebook]) {
ServiceMsg = #"Article Shared!";
} else if([act isEqualToString:UIActivityTypeMessage]) {
ServiceMsg = #"SMS sent!";
} else if([act isEqualToString:UIActivityTypeAddToReadingList]) {
ServiceMsg = #"Added to Reading List";
} else if([act isEqualToString:UIActivityTypeCopyToPasteboard]){
ServiceMsg = #"Copied Link";
}
if ( done )
{
UIAlertView *Alert = [[UIAlertView alloc] initWithTitle:ServiceMsg message:#"" delegate:nil cancelButtonTitle:#"ok" otherButtonTitles:nil];
[Alert show];
}
}];
}
Help is appreciated!
Following line is the issue
AVC.popoverPresentationController.sourceView = _webView;
You will have to put iOS8 condition in order popoverPresentationController is introduced for iOS 8 and later so you can not use it with iOS 7
For checking for iOS8 you can define a macro like found from here
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
And use it in following way.
NSURL *linkURL = [NSURL URLWithString:_DetailModal1[4]];//article url
NSMutableAttributedString *stringText = [[NSMutableAttributedString alloc] initWithString:_DetailModal1[0]];//_DetailModal1[0] contain article title////
[stringText addAttribute:NSLinkAttributeName value:linkURL range:NSMakeRange(0, stringText.length)];
NSArray * itemsArray = #[[NSString stringWithFormat:#"%#",_DetailModal1[0]], [NSURL URLWithString:_DetailModal1[4]]];
NSArray * applicationActivities = nil;
UIActivityViewController * AVC = [[UIActivityViewController alloc] initWithActivityItems:itemsArray applicationActivities:applicationActivities];
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")){
AVC.popoverPresentationController.sourceView = _webView;
}
[self presentViewController:AVC animated:YES completion:nil];
Refer this for more info about what has changed for UIActivityViewController in iOS8
A lot might argue that checking for existence of the class explicitly is better than checking a hard coded version number. UIPopoverPresentationController may be deprecated at some future point, or there might be a (future ?) device which does not support the class, like the iPhone never used to support UIPopoverController or UISplitViewController..
if ( NSClassFromString(#"UIPopoverPresentationController") ) {
AVC.popoverPresentationController.sourceView = _webView;
}
In Swift, You can use '?' instead checking OS version.
AVC.popoverPresentationController?.sourceView = _webView

EXC_BAD_ACCESS code=2 address=0x0

I am using a UIActivityViewController in my app, and I am getting a EXC_BAD_ACCESS code=2 crash on iOS 6, but not iOS 7. Here is the code:
NSArray *activityItems;
NSString *shareText = [NSString stringWithFormat:NSLocalizedString(#"Listen to", nil), self.currentChannel.title, self.currentChannel.itunesUrl];
if (self.currentChannel.mediumThumbnailImage)
{
activityItems = #[shareText, self.currentChannel.mediumThumbnailImage];
}
else
{
activityItems = #[shareText];
}
UIActivityViewController *activityController = [[UIActivityViewController alloc]
initWithActivityItems:activityItems
applicationActivities:nil];
[activityController setCompletionHandler:^(NSString *activityType, BOOL completed) {
// once they have shared, check where they shared the content for analytics
if (completed)
{
NSString *actionName = nil;
NSString *socialName = nil;
if ([activityType isEqualToString:kMailActivity]) {
actionName = kSocialEmail;
socialName = kMail;
} else if ([activityType isEqualToString:kMessageActivity]) {
actionName = kSocialChat;
socialName = kMessage;
} else if ([activityType isEqualToString:kFacebookActivity] || [activityType isEqualToString:kTwitterActivity]) {
actionName = kSocialShare;
socialName = kFacebook;
}
if (actionName && socialName)
{
NSDictionary *data = #{kSocialName: socialName, kSocialContent: shareText};
if (data)
{
[ADBMobile trackAction:actionName data:data];
}
}
}
}];
if (activityController)
{
[activityController setExcludedActivityTypes:
#[UIActivityTypeAssignToContact,
UIActivityTypePrint,
UIActivityTypePostToWeibo,
UIActivityTypeSaveToCameraRoll,
UIActivityTypeAirDrop]];
[self presentViewController:activityController
animated:YES completion:nil];
}
I have used NSZombies to narrow down where the crash is happening, and it is happening when I call setExcludedActivityTypes: in iOS 6. I know that this error means that an object has been overreleased, and I am touching memory that doesn't belong to me. What I don't understand is why this crash is only occurring in iOS 6. Does anyone see something that could be causing this?
UIActivityTypeAirDrop is only available in iOS 7 and not in iOS 6.
You can check the availability of a constant like this:
if(&UIActivityTypeAirDrop) {
// UIActivityTypeAirDrop is available
} else {
// Its not available. Don't use it.
}
(I'm making this a community wiki, because I just copied the comment from user Larme above.)

Resources