How to share things with a UIActivityViewController

来源:互联网 时间:1970-01-01

Since iOS 6 it has been really easy to share many complex objects, thanks to the UIActivityViewController. All we have to do is wrap our object (or objects) in an array, give that to the activity view controller, and present it.

To share a UIImage on iPhone for example, we’ll do something like this:

- (IBAction)shareImageDefault:(id)sender {// grab an item we want to shareUIImage *image = [UIImage imageNamed:@"three"];NSArray *items = @[image];// build an activity view controllerUIActivityViewController *controller = [[UIActivityViewController alloc]initWithActivityItems:items applicationActivities:nil];// and present it[self presentViewController:controller animated:YES completion:^{// executes after the user selects something}];}

We need the array because we could be sharing more than just one item. The result looks something like the screenshot above: two rows of shareable icons appear, the top one representing “share” options, and the bottom one representing “action” options. Each of these is a UIActivity object. If ever you need to create your own activities, you can add them to either top or bottom category (but we won’t cover how to do that here).

On iPad, this type of presentation will crash – and Apple would like us to use a Popover presentation instead. It gets a bit long to show this here every time, so I’ve refactored this call into its own method and will be referring to it going forward:

- (void)presentActivityController:(UIActivityViewController *)controller { // for iPad: make the presentation a Popover controller.modalPresentationStyle = UIModalPresentationPopover; [self presentViewController:controller animated:YES completion:nil]; UIPopoverPresentationController *popController = [controller popoverPresentationController]; popController.permittedArrowDirections = UIPopoverArrowDirectionAny; popController.barButtonItem = self.navigationItem.leftBarButtonItem; Excluding certain activities

If called as mentioned above, iOS will compile a list of all possible activities our item can be shared as. UIImages for example could be saved to our Photo Library, Air-dropped, Facebooked or emailed, among other things.

To trim this list down to something more relevant, we can exclude certain activities. Imagine we don’t want the option to share on Facebook and Twitter, we can do it like this:

- (IBAction)shareImageExcludeSocial:(id)sender {// grab an item we want to shareUIImage *image = [UIImage imageNamed:@"three"];NSArray *items = @[image];// build an activity view controllerUIActivityViewController *controller = [[UIActivityViewController alloc]initWithActivityItems:items applicationActivities:nil];// exclude several itemsNSArray *excluded = @[UIActivityTypePostToFacebook, UIActivityTypePostToTwitter];controller.excludedActivityTypes = excluded;// and present it[self presentActivityController:controller];}

The UIActivity class has a type property, each of which is an NSString, and Xcode knows them all. You can literally exclude anything and everything from this list (check the class reference below for all types you can include here).

Reacting to user selections

The UIActivityViewController calls a completion handler block we can access. In it we’re given the activity the user selected (as reverse-domain string), a BOOL ti indicate if the user used a sharing option (YES) or if the cancel button was pressed (NO), and error object and possible returned objects.

Sadly the Apple documentation isn’t very obvious how to do this at the time of writing, and it took some tinkering to find this out:

// access the completion handlercontroller.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *error){// react to the completionif (completed) {// user shared an itemNSLog(@"We used activity type%@", activityType);} else {// user cancelledNSLog(@"We didn't want to share anything after all.");}if (error) {NSLog(@"An Error occured: %@, %@", error.localizedDescription, error.localizedFailureReason);}};

In essence, we need to create our own block through which the above objects are available, and add it to our controller. It’s slightly different from using a block that’s part of a method signature or implementing delegate methods – but this approach works just the same.

The activityType will be something like typecom.apple.UIKit.activity.SaveToCameraRoll, through which you can test which activity was selected by the user. If the completed BOOL returns NO, the cancel button was pressed.

Demo Project

I’ve got a working demo project on GitHub. Feel free to take a look at it:

https://github.com/versluis/Activity-Demo Further Reading


相关阅读:
Top