先介绍下UIActivityController
如下图,UIActivityController可以实现系统自带的分享功能,不需要集成SDK,支持Airdrop隔空投送、连接打印机、复制链接等功能。可以分享到短信、备忘录、邮件、微信、微博。QQ等。
实现UIActivityController功能
实现方法还是很简单的,直接上代码。
/*
先创建要分享的内容,放在一个数组里
*/
//分享的URL
NSURL *urlItem = [NSURL URLWithString:@"https://www.baidu.com"];
//分享的text
NSString *textItem = @"分享text";
//分享的图片
UIImage *imageItem = [UIImage imageNamed:@"icon.png"];
//加入数组
NSArray *activityItemsArray = @[urlItem,textItem,imageItem];
//初始化UIActivityViewController
UIActivityViewController *activityViewController = [[UIActivityViewController alloc]initWithActivityItems:activityItemsArray applicationActivities:nil];
//弹出分享页面
[self presentViewController:activityViewController animated:YES completion:nil];
如果你想关闭系统分享中的部分功能,可以在excludedActivityTypes中设置。代码如下。
//需要关闭的功能
activityViewController.excludedActivityTypes = @[UIActivityTypeCopyToPasteboard,UIActivityTypePostToFacebook,UIActivityTypePostToWeibo];
UIActivityType里的功能都可以关闭。
UIKIT_EXTERN UIActivityType const UIActivityTypePostToFacebook NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypePostToTwitter NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypePostToWeibo NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED; // SinaWeibo
UIKIT_EXTERN UIActivityType const UIActivityTypeMessage NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypeMail NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypePrint NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypeCopyToPasteboard NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypeAssignToContact NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypeSaveToCameraRoll NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypeAddToReadingList NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypePostToFlickr NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypePostToVimeo NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypePostToTencentWeibo NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypeAirDrop NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypeOpenInIBooks NS_AVAILABLE_IOS(9_0) __TVOS_PROHIBITED;
UIKIT_EXTERN UIActivityType const UIActivityTypeMarkupAsPDF NS_AVAILABLE_IOS(11_0) __TVOS_PROHIBITED;
分享完成后可以在回调方法里获取到分享的类型、是否分享成功等信息,也可以在分享完成后做相应的处理。
//完成分享回调方法
activityViewController.completionWithItemsHandler = ^(UIActivityType _Nullable activityType, BOOL completed, NSArray * _Nullable returnedItems, NSError * _Nullable activityError) {
//分享完成后在这里做相应的处理
};
这样一个系统分享的基本功能就完成了。
遇到的问题
Airdrop隔空投送失败问题
使用Airdrop隔空投送时会遇到分享失败,提示信息为“无法同时接收所有的这些项目”。如下图。解决办法就是在activityItemsArray数组中不要加入图片只传URL和text就可以了。
NSArray *activityItemsArray = @[urlItem,textItem];
但也会有个问题就是,这样无法做到只让Airdrop不分享图片而其他功能仍需要分享图片。解决办法就需要自定义要分享的Item。首先创建子类ActivityItemProviderImage继承UIActivityItemProvider这个类,然后实现这个方法:
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(nullable UIActivityType)activityType;
在此方法里可以通过activityType判断分享的功能,如果是Airdrop就传空。实现代码如下。
.h文件
#import <UIKit/UIKit.h>
@interface ActivityItemProviderImage : UIActivityItemProvider
@property (nonatomic,strong) UIImage *imageToShare;
@end
.m文件
#import "ActivityItemProviderImage.h"
@implementation ActivityItemProviderImage
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
{
if ([activityType isEqualToString:UIActivityTypeAirDrop]) {
return nil;
}else {
return _imageToShare;
}
}
@end
然后在创建activityItemsArray时就把这个自定义的imageItem添加进去就可以了。
//分享的URL
NSURL *urlItem = [NSURL URLWithString:@"https://www.baidu.com"];
//分享的text
NSString *textItem = @"分享text";
//分享的图片
UIImage *imageToShare = [UIImage imageNamed:@"icon.png"];
//自定义imageItem
ActivityItemProviderImage *imageItem = [[ActivityItemProviderImage alloc] initWithPlaceholderItem:imageToShare];
imageItem.imageToShare = imageToShare;
//加入数组
NSArray *activityItemsArray = @[urlItem,textItem,imageItem];
//初始化UIActivityViewController
UIActivityViewController *activityViewController = [[UIActivityViewController alloc]initWithActivityItems:activityItemsArray applicationActivities:nil];
//弹出分享页面
[self presentViewController:activityViewController animated:YES completion:nil];
这样Airdrop的分享功能就可以正常使用了,且其他的分享功能也可以分享图片。
QQ浏览器分享到搜索界面问题
这个问题就是当你分享的Items中既有URL也有text的时(不添加图片,添加图片后会不显示分享到QQ浏览器功能),分享到QQ浏览器就会打开搜索,搜索内容为分享的text(复制链接功能同理会复制URL+text),而不是我们想要的直接打开分享的URL。解决办法就是只传URL不传text这样就会直接打开链接了。代码和上面解决Airdrop的问题类似,需要自定义要分享的Item。要注意的是UIActivityType里并没有提供QQ浏览器的类型,可以在之前的这个方法里
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(nullable UIActivityType)activityType;
打印activityType,获取到QQ浏览的Type为“com.tencent.mttlite.share”。然后进行判断处理。其他UIActivityType里没有的类型也可以这样获取到。
分享到短信页面时没有返回按钮无法返回
如果分享到短信页面时没有返回按钮,检查你的项目里有没有FDFullscreenPopGesture这个滑动返回的第三方库。如果有的话在这个方法的里面加入这段代码屏蔽掉短信界面。
- (void)fd_pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
//解决短信界面没取消按钮问题
if ([self isKindOfClass:NSClassFromString(@"MFMessageComposeViewController")]) {
[self fd_pushViewController:viewController animated:animated];
return;
}
分享到新浪微博页面顶部遮挡问题
如果你用的iOS11的系统分享到微博,可能会遇到分享页面顶部会有部分被导航栏遮挡住的问题,如下图。这个是因为iOS11的特性,解决办法是在弹出分享页面之前判断iOS11系统,设置ScrollView的contentInsetAdjustmentBehavior为UIScrollViewContentInsetAdjustmentAutomatic。
if (@available(iOS 11.0, *)) {
UIScrollView.appearance.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAutomatic;
}
然后在分享完成后再设置成UIScrollViewContentInsetAdjustmentNever,这样分享到微博的界面就正常了。
//完成分享回调方法
activityViewController.completionWithItemsHandler = ^(UIActivityType _Nullable activityType, BOOL completed, NSArray * _Nullable returnedItems, NSError * _Nullable activityError) {
if (@available(iOS 11.0, *)) {
UIScrollView.appearance.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
};