UIActivityViewController

做社会化分享,经典的做法就是在各个社会化平台申请 App Key,然后集成各个平台的 SDK,并分别进行开发。更简单的方式是用类似友盟分享 SDK、ShareSDK 之类的集成化 SDK,让多平台分享的开发更加容易。之前我和团队就是采用这种方式。

其实 iOS 本身提供了一种分享的方式,App Store 里的分享就是一个实现的例子:
UIActivityViewController

这个弹出的分享框,叫做 UIActivityViewController。通过它来实现分享,好处是样式统一、实现简单,更重要的是它直接使用系统中设置的平台账号,并且不需要对应用进行授权。这一点降低了用户分享的心理负担。同时,开发者不需要去平台为应用申请 App Key,也一定程度上降低了开发的门槛。

但正是因为这种分享不依附于应用,所以也会带来一些缺点。比如分享出去的东西会显示“来自 iOS” 而不是你的应用,也导致了不能进行用户统计。而且通过这个只能做分享,不能用做 SSO 登录。对于只需要分享的简单场景下,用 UIActivityViewController 完全足够并且更加合适,所以我在词记里尝试了一下。

基本的实现非常简单,把需要分享的内容,可以是文字、图片、链接,传入初始化方法即可:

1
2
3
4
NSString *str = @"Hello";
NSURL *url = [NSURL URLWithString:@"http://www.stoneark.org"];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[str, url] applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:nil];

如果需要为不同平台提供不同的分享内容,或者生成某个分享内容的过程较复杂,可以为这个内容创建一个 UIActivityItemProvider 的子类,并实现方法 -(id)activityViewController: itemForActivityType:,如:

ShareTextProvider
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@interface MonthViewShareTextProvider : UIActivityItemProvider
@property (strong, nonatomic) NSString *shareText;
@end
@implementation MonthViewShareTextProvider
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType {
if ([activityType isEqualToString:UIActivityTypeSaveToCameraRoll] ||
[activityType isEqualToString:UIActivityTypePrint] ||
[activityType isEqualToString:UIActivityTypeCopyToPasteboard] ||
[activityType isEqualToString:@"com.tencent.xin.sharetimeline"] ) {
// 保存到相册、打印、复制、分享到微信,不提供文字
return nil;
} else {
return _shareText;
}
}
@end

利用它去初始化 UIActivityViewController 时:

1
2
3
4
ShareTextProvider *textProvider = [[ShareTextProvider alloc]initWithPlaceholderItem:@"Hello"];
[textProvider setShareText:@"Hello"];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc]initWithActivityItems:@[textProvider] applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:nil];

注意初始化方法里的 PlaceholderItem,它应该是能够正确反应内容数据类型的简单数据。在弹出的 UIActivityViewController 里,会根据这些 PlaceholderItem 的类型,来决定显示哪些选项,此时并不会去调用 ItemProvider 里的方法。比如有两个 UIImage,则会显示“存储 2 张图片”;如果没有 UIImage,则不会显示存储图片这一个按钮。当你真正点击某一项分享渠道时,才会调用其 itemForActivityType 方法来得到真正的内容。

你可能注意到了,上面微信的 activity type 用了字符串 @”com.tencent.xin.sharetimeline”。而关于 UIActivityType,查看 UIActivityType.h,可以看到这些:

UIActivity.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
UIKIT_EXTERN NSString *const UIActivityTypePostToFacebook NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypePostToTwitter NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypePostToWeibo NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED; // SinaWeibo
UIKIT_EXTERN NSString *const UIActivityTypeMessage NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypeMail NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypePrint NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypeCopyToPasteboard NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypeAssignToContact NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypeSaveToCameraRoll NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypeAddToReadingList NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypePostToFlickr NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypePostToVimeo NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypePostToTencentWeibo NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypeAirDrop NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIActivityTypeOpenInIBooks NS_AVAILABLE_IOS(9_0) __TVOS_PROHIBITED;

里面并没有发现微信。通过运行时打印,可以整理出如下的表格:

方式 字符串常量 字符串内容
AirDrop UIActivityTypeAirDrop com.apple.UIKit.activity.AirDrop
SMS UIActivityTypeMessage com.apple.UIKit.activity.Message
Mail UIActivityTypeMail com.apple.UIKit.activity.Mail
备忘录 N/A com.apple.mobilenotes.SharingExtension
新浪微博 UIActivityTypePostToWeibo com.apple.UIKit.activity.PostToWeibo
iBooks UIActivityTypeOpenInIBooks com.apple.UIKit.activity.OpenInIBooks
QQ N/A com.tencent.mqq.ShareExtension
微信 N/A com.tencent.xin.sharetimeline
Twitter UIActivityTypePostToTwitter com.apple.UIKit.activity.PostToTwitter
Facebook UIActivityTypePostToFacebook com.apple.UIKit.activity.PostToFacebook
Flicker UIActivityTypePostToFlickr com.apple.UIKit.activity.PostToFlickr
Vimeo UIActivityTypePostToVimeo com.apple.UIKit.activity.PostToVimeo
腾讯微博 UIActivityTypePostToTencentWeibo com.apple.UIKit.activity.TencentWeibo
提醒事项 N/A com.apple.reminders.RemindersEditorExtension
保存到相册 UIActivityTypeSaveToCameraRoll com.apple.UIKit.activity.SaveToCameraRoll
指定到联系人 UIActivityTypeAssignToContact com.apple.UIKit.activity.AssignToContact
复制到剪贴板 UIActivityTypeCopyToPasteboard com.apple.UIKit.activity.CopyToPasteboard
打印 UIActivityTypePrint com.apple.UIKit.activity.Print
添加到阅读列表 UIActivityTypeAddToReadingList com.apple.UIKit.activity.AddToReadingList

可以查阅 NSHipster上的这篇文章了解有关 UIActivityViewController 的更多信息。