Sharing functionality for an rss feed article - ios

My rss app is almost complete but I need to have a "share" button on the top right corner of the web view for the articles. I have the code setup so far to show the "action" button right next to the title of the article but since there is no real code implemented it doesn't do anything :
I implemented that by basing it on code that was used for the table view cells where there is a "refresh" option implemented and I just changed the icon. I used a free open source project to put this app together and i'm having a little bit of trouble figuring out how to make that button show the share sheet that pulls up from the bottom of the app, like this:
(image from google)
I tried to implement a button dirtectly into the nav bar but I can't since the web view covers the whole screen:
So, since I couldn't put a button directly into the controller I had to encode it in like so:
In my RSSDetail.m class inside the " -(void)viewDidLoad { " :
self.navigationItem.rightBarButton = [[UIBarButtonItem = [[UIBarButtonItem
alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemAction target:self
action#selector(shareButton)];
and I also have this inside the same class file :
-(void) shareButton {
self.webView.userInteractionEnabled = YES;
self.webView.aplha = 0.3;
}
So as you can see, this little bit of code in that class puts the icon where I want it. But my question is, is there code i can implement into my " -(void) shareButton " method that will implement the sharing functionality?
Also, I need for the button to actually say "Share" as opposed to the icon, is there anyway I can change the code for the "Action" rightBarButton method to allow me to input the word instead of an icon?
Thanks in advance

As I understand you want to implement iOS native sharing functionality. Here is an example of implementation:
- (void)shareButtonPressed {
// 1
// If you want to use UIImage, make sure you have image with that name, otherwise it will crash.
NSArray *activityItems = #[#"Message to share", [UIImage imageNamed:#"imageToShare"]];
// 2
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
// 3
activityViewController.excludedActivityTypes = #[UIActivityTypeCopyToPasteboard, UIActivityTypeAirDrop, UIActivityTypeAssignToContact, UIActivityTypeAddToReadingList, UIActivityTypePrint, UIActivityTypeSaveToCameraRoll, UIActivityTypeMessage, UIActivityTypeMail];
// 4
[activityViewController setCompletionHandler:^(__unused NSString *activityType, __unused BOOL completed){
// Custom completion implementation
}];
[self presentViewController:activityViewController animated:YES completion:NULL];
}
Description:
Prepare activity items which you want to share such string, image, URL.
Initialize activity view controller with the items you want to share + custom activities (only if needed). Custom activities means that you will create your own buttons using UIActivity with own actions, images, titles (more info here). For example, implement sharing to a third party app which does not have share extension.
Here you can specify excluded activity types. In this example I have removed everything such as copy, airdrop and etc.
In completion block you can see which activityType was selected and whether user cancelled or not.
More information on UIActivityViewController can be found here.
Regarding second part of your question about UIBarButtonItem. UIBarButtonItem can be initialised with custom title using this:
UIBarButtonItem *shareButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Share" style:UIBarButtonItemStylePlain target:self action:#selector(shareButtonPressed)];
self.navigationItem.rightBarButtonItem = shareButtonItem;
Be aware that UIBarButtonItem has UIBarButtonItemStyle which you can change. UIBarButtonItemStylePlain (will create a button with a regular font) and UIBarButtonItemStyleDone (will create a button with a bold font).

Related

Can't get a Share Button to work in my iOS App?

I can't get a Share button to work in my current app, I successfully had one in my previous app but I can't get it to work in my new app. I think this may be due to my first app having only a single ViewController whereas this app has multiple. I am trying to do this in a different view controller, not the default main one. Not sure what I'm doing wrong.
// MoreMenuViewController.h
#import <UIKit/UIKit.h>
#interface MoreMenuViewController : UIViewController
- (IBAction)tellFriend:(id)sender;
// MoreMenuViewController.m
#import "MoreMenuViewController.h"
#implementation MoreMenuViewController
- (IBAction)tellFriend:(id)sender
{
NSString *shareText = [NSString stringWithFormat:#"Check out Stories With Friends, a new word game for iPhone!"]; // Share message
NSArray *itemsToShare = #[shareText];
UIActivityViewController *activityVC =
[[UIActivityViewController alloc] initWithActivityItems:itemsToShare applicationActivities:nil];
activityVC.excludedActivityTypes = #[];
[MoreMenuViewController:activityVC animated:YES completion:nil];
}
For the last line of code I get an error: No known class method for selector 'animated:completion:.'
Help would be much apperciated, thanks!
You need to call this method from self instead of MoreMenuViewController:
[self presentViewController:activityVC
animated:YES
completion:nil];
You also don't need to call this setter if you don't need to excluded types:
activityVC.excludedActivityTypes = #[];
UPDATE:
Despite now being able to click the button the app crashes: -[MoreMenuViewController tellAFriend:]
It's because the name of your method is tellFriend: and NOT tellAFriend: you must had renamed your method from the code without refactoring so the linked IBAction has no clue of the change. What you need to do is remove this link made from your Storyboard to your implementation file.
Click on your button then click on the cross where the action is linked to tellAFriend:
Try [self presentViewController:activityVC animated:YES completion:nil];
instead

How to programmatically make text selectable and provide popup menus to go to another app

I am trying to implement a feature in iOS project that when you select a piece of text and highlight it you can then choose from the menu options to use another app like the default dictionary. Is it possible to do this? If so where can I find such documentation or tutorials?
You are describing the iOS menu. Look at the documentation on classes such as UIMenu, UIMenuItem, and UIMenuController.
I've found a solution to my problem.
Thanks to the author of this article:
http://blog.studiovillegas.com/2014/02/06/ios-uipasteboard-uimenucontroller-and-uimenuitem/
To add a custom menu item on to the default menu controller.
ViewController.h
- (void)longPressGestureRecognizer:(UIGestureRecognizer *)recognizer
{
UIMenuItem *mi = [self.label menuItemOpenPleco];
UIMenuController *menuController = [UIMenuController sharedMenuController];
menuController.menuItems = #[mi];
}
PasteboardLabel {h,m}
#interface PasteboardLabel : UILabel
- (UIMenuItem *)menuItemOpenPleco;
#end
#implementation PasteboardLabel
- (UIMenuItem *)menuItemOpenPleco
{
return [[UIMenuItem alloc] initWithTitle:#"Open Pleco" action:#selector(openPleco:)];
}
- (void)openPleco:(id)sender
{
NSString *selectedText = [self textInRange:[self selectedTextRange]];
UIPasteboard *pb = [UIPasteboard generalPasteboard];
pb.string = selectedText;
NSString *urlString = [NSString stringWithFormat:#"plecoapi://x-callback-url/q?s=%#", pb.string];
NSURL *url = [[NSURL alloc] initWithString:urlString];
[[UIApplication sharedApplication] openURL:url];
}
#end
I've found that there's a dearth of examples of adding custom menu items, or explanations of how they work. So I wanted to resolve that by sharing a few important tidbits then showing an example.
The UIMenuController "talks" with UIViews, not with UIViewControllers. This means that your UIMenuController related code needs to go into subclasses of UIView rather than a UIViewController.
Notice the word The at the start of my prior example. There's only one UIMenuController, a singleton which is shared from when your application first starts until it ends. This means that you should only add your item once, and that you shouldn't be writing over the existing array of items.
The appearance of the button in the UIMenu is based on whether or not the UIView that was tapped responds to the selector. This means you need to implement the method if you want the button to appear, and that you don't need to worry about it appearing when unrelated views are tapped unless you pick a selector name for which other UIViews also have methods.
So, having said all that, I made a subclass of a UITextView (which means its a subclass of UIView per my first bullet) and then I gave it this initialize method, along with an implementation for my selector.
+ (void)initialize {
static dispatch_once_t addInsert;
dispatch_once(&addInsert, ^{
UIMenuController *mController = [UIMenuController sharedMenuController];
UIMenuItem *insert = [[UIMenuItem alloc] initWithTitle:#"Insert..."
action:#selector(insert:)];
mController.menuItems = [mController.menuItems arrayByAddingObject:insert];
});
}
- (void)insert:(id)sender {
NSLog(#"Insert... pressed!");
}
The important points above here:
It's in the class initialize method, which is called by the runtime before the first time any other method in your class is invoked. In practice means the code is handled just before the first time an instance of your custom view will be appearing on screen.
I added a dispatch_once guard around it. If my class is subclassed, it's possible that those subclasses will call this initialize method. Maybe those subclasses show up before this one does, so I don't want to prevent the initialize method from running then. I just want to prevent it from running multiple times. Thus why I wrapped the code in a dispatch_once.
I didn't just set the menuItems to a new array of items - I assigned it to a new array of items that extended the existing array of items with my new item.
Hope you find all of that helpful. It's not very complicated, and you can certainly go about implementing my second point in other ways - I tried to pick a way that seemed safest to me, but there are certainly simpler ways of doing it.

Is it possible to present a UIDocumentInteractionController for multiple items?

The Photos app in iOS 7 allows you to select multiple photos, tap "Share" and be presented with a document interaction controller with the appropriate options for multiple items.
The Camera app goes one further and even updates the document interaction controller's options in real time as you select and deselect photos.
However, the UIDocumentInteractionController class seems only to allow for a single URL parameter.
Is it possible to do what the Photos and Camera apps do using public API?
- (void)showShareDialog
{
UIImage *image = [UIImage imageWithCGImage:self.imgView.image.CGImage];
NSArray* dataToShare = #[image, image2, image3]; // ...or whatever pieces of data you want to share.
UIActivityViewController* activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:dataToShare
applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:^{
}];
}
I think this should help
Store the URLs of the selected items in an array. You can change the actions displayed depending upon the number of elements in the array. After the user makes his/her selection, you can loop through the URLs and apply the selected action.

Provide different content to different services within a single UIActivityViewController

I'd like to provide different content to the different services in a UIActivityIndicatorView. For example, an HTML string for email, standard string for Facebook/Twitter, and an image for Copy. All of this happens within a single popover window.
I don't think this is possible. As I was playing around with all of the involved classes, I notices that the services that appear in the activity view change as the content type I provided it changed. In other words, when I provided a string, set A of services appeared. When I provided an image, set B of services appeared.
Next I tried adding both string and image thinking that possibly it would provide different content, however this just adds both the string and image to the services (for example an email is created with a string, then the image below).
Here is how I am providing string values (which are html links):
-(void)shareButtonTouchUpInside:(SMActionToolbarViewController*)sender{
// Reposition anchor view for UIPopoverController to point at
[self repositionAnchorViewToButtonFrame:self.actionToolbarViewController.shareButtonFrame];
// Asynch download of image
[SMUtility downloadAsset:self.selectedAsset completion:^(UIImage *image) {
// Create image source
SMActivitySource *activityImageSource = [[SMActivitySource alloc]initWithImage:image];
// Create string source
NSString *assetsString = [SMUtility assetsString:[NSArray arrayWithObject:self.selectedAsset]];
SMActivitySource *activityStringSource = [[SMActivitySource alloc]initWithString:assetsString];
// Present UIActiviyViewController within an UIPopoverController
NSArray *items = [#[activityImageSource, activityStringSource]mutableCopy];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc]initWithActivityItems:items applicationActivities:nil];
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed){
// TODO: Populate mixpanel data
[SMMixPanel eventSharePhotoMethod:#"Unknown"];
}];
self.buttonPopoverController = [[UIPopoverController alloc] initWithContentViewController:activityViewController];
[self.buttonPopoverController presentPopoverFromRect:self.anchorView.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}];
}
You should subclass UIActivityItemProvider or create objects that conform to UIActivityItemSource. Pass in an array of those (one for each thing you want to share), and have some of them return nil depending on the chosen activity in the activityViewController:itemForActivityType: call.
This Question has been asked time and time again, the only way to fix it is to make your own UIActivity, see apple documentation on how to do that. Here is a link: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIActivity_Class/Reference/Reference.html

Certain UIActivityViewController services missing from my app

I have implemented UIActivityViewController within my app and can successfully share both strings and images. However, I notice that when you share an image within the iOS Photos app, there are some services that do not appear in my app. Namely Print, Use as Wallpaper, and Assign To Contact, and Photo Stream. My app is able to use Mail, Message, Facebook, Twitter, and Copy just fine.
I am thinking that either:
1.) These extra services have been implemented as custom services within the Photos app using UIActivityItemProvider, UIActivityItemSource, etc..
2.) The data that I am providing is not in the correct format to be used with these services.
I have read through the documentation a few times, but don't seem to see anything about it.
Edit: Showing code as requested:
#define SM_SHARE_IMAGE_AND_STRING 1
-(void)actionToolbarViewControllerUserTappedShareButton:(SMActionToolbarViewController*)sender{
// Reposition anchor view for UIPopoverController to point at
[self repositionAnchorViewToButtonFrame:self.actionToolbarViewController.shareButtonFrame];
// Asynch download of image
[SMUtility downloadAsset:self.selectedAsset completion:^(UIImage *image) {
// Create image source
SMActivitySource *activityImageSource = [[SMActivitySource alloc]initWithImage:image];
#if defined(SM_SHARE_IMAGE_AND_STRING)
// Create string source
NSString *assetsString = [SMUtility assetsString:[NSArray arrayWithObject:self.selectedAsset]];
SMActivitySource *activityStringSource = [[SMActivitySource alloc]initWithString:assetsString];
// Present UIActiviyViewController within an UIPopoverController
NSArray *items = [#[activityImageSource, activityStringSource]mutableCopy];
#else
NSArray *items = [#[activityImageSource]mutableCopy];
#endif
UIActivityViewController *activityViewController = [[UIActivityViewController alloc]initWithActivityItems:items applicationActivities:nil];
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed){
[SMMixPanel eventSharePhotoMethod:#"Share"];
}];
self.buttonPopoverController = [[UIPopoverController alloc] initWithContentViewController:activityViewController];
[self.buttonPopoverController presentPopoverFromRect:self.anchorView.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}];
}
The Print, and Assign To Contact activities are standard activities shown by the UIActivityViewController as long as you provide the proper data.
You must provide a UIImage for the Assign To Contact activity. See the docs for UIActivityTypeAssignToContact. See the docs for UIActivityTypePrint for details on what it accepts.
The "Use As Wallpaper" seems to be a custom activity shown only in the Photos app.

Resources