iOS 开发中, 我们经常会用到分享这个功能我们希望把自己的 APP 里面好东西通过分享的渠道推广出去, 或者看到好的东西我们希望通过分享到 APP 与好友共享为了实现这种功能, 业界常用的做法是通过集成 SDK(如微信)或第三方 (如友盟分享) 去做, 但是这样做有个弊端就是我们得配置所有想分享的平台的 scheme, 分享的时候我们得调起相应的 APP 怎么样做到像 Safari 那样分享呢?
这里有两个问题: 1, 怎么让自己的 APP 出现在 Safari 分享栏的选项里, 让用户可以直接通过这种方式分享内容到咱们自己的 APP2 在咱们自己的 APP 里分享时怎么像 Safari 一样分享, 而不是集成 SDK
Share extensions
share extentsion 的出现解决了咱们的第一个问题, 它的 (基础) 使用也特别简单先按照
file - >new - >target - >Share Extentsion - >Next - >Finish - >Activate
的步骤添加 Share Extension 这时候我们会发现 active scheme 已经自动变成咱们刚才新建的 target 了, 而不是原来的 target 了(如下图)
点击 run, 然后选择一个 APP(这里选的 Safari)作为 Host app, 运行之后发现测试机已经自动启动 Safari 了我们随便打开一个网页, 然后点分享, 惊喜出现了, 咱们的 APP 已经静静的躺在分享栏的选项里了, 见下图左图
点击 Post, 再启动咱们自己的 APP, 可以发现刚才在浏览器分享的内容已经展示出来了(这里用到了 APP Group 服务, 此处暂且略过不提), 见上图右图
新建的 extension 里有个默认的 ShareViewController, 它继承于
SLComposeServiceViewController
, 关于分享的操作都在这里完成在分享之前, 我们可以通过判断来决定是否可以分享, 比如如果文字里包含皇上两个字, 则不让分享, Post 按钮置灰, 如下图
代码如下:
- override func isContentValid() - >Bool {
- // 如果文字中包含皇上两个字, 则不可分享
- if contentText.contains("皇上") {
- return false
- }
- return true
- }
分享的数据处理则主要是在 didSelectPost()里处理:
- override func didSelectPost() {
- print("分享")
- // 处理新的分享数据前清除老数据
- let userDefaults = UserDefaults(suiteName: "group.kefan.com.KFAShareDemo")
- if let ud = userDefaults {
- ud.set(nil, forKey: "title_key")
- ud.set(nil, forKey: "content_key")
- ud.set(nil, forKey: "url_key")
- }
- let item = self.extensionContext!.inputItems.first as? NSExtensionItem
- guard item != nil else {
- print("分享内容为空")
- self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
- return
- }
- // 分享标题
- if let title = item!.attributedTitle {
- print(title.string)
- if let ud = userDefaults {
- ud.set(title.string, forKey: "title_key")
- }
- }
- // 分享内容
- if let content = item!.attributedContentText {
- print(content.string)
- if let ud = userDefaults {
- ud.set(content.string, forKey: "content_key")
- }
- }
- // 分享附件
- if let attachments = item!.attachments as? [NSItemProvider] {
- for provider in attachments {
- // 如果分享的是链接
- if provider.hasItemConformingToTypeIdentifier("public.url") {
- provider.loadItem(forTypeIdentifier: "public.url", options: nil, completionHandler: { (data, error) in
- let url = data as! URL
- // 把 url 存在 UserDefaults 里用来与容器程序共享
- if let ud = UserDefaults(suiteName: "group.kefan.com.KFAShareDemo") {
- ud.set(url, forKey: "url_key")
- }
- })
- }
- }
- }
- self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
- }
UIActivityViewController 和 SLComposeViewController
这两个类则可以为我们解决第二个问题不同的是,
UIActivityViewController
把支持的分享的 APP 和操作都展示出来, 让我们选择, 跟 Safari 界面类似, 而
SLComposeViewController
则是直接分享给目标 APP 如下图, 左图点击分享用的
UIActivityViewController
, 所以出现的一个选择界面, 右图点微信通过
SLComposeViewController
直接分享给微信
代码分别如下:
- if SLComposeViewController.isAvailable(forServiceType: "com.tencent.xin.sharetimeline") {
- let vc = SLComposeViewController(forServiceType: "com.tencent.xin.sharetimeline")
- guard vc != nil else {
- return
- }
- vc!.setInitialText("O(_)O 哈哈~, 给您分享一个链接")
- vc!.add(UIImage(named: "headIcon"))
- vc!.add(url)
- vc!.completionHandler = {(result: SLComposeViewControllerResult) -> () in
- if result == SLComposeViewControllerResult.cancelled {
- print("取消分享")
- }else {
- print("分享")
- }
- }
- present(vc!, animated: true, completion: nil)
- }
- let vc = UIActivityViewController(activityItems: ["分享标题", UIImage(named: "headIcon")!, url], applicationActivities: nil)
- present(vc, animated: true, completion: nil)
- TODO
因为是一时兴起的小实践, 所以还有很多细节有待深入优化比如 ShareViewController 分享界面的自定义, 比如
SLComposeViewController
怎么同时分享标题内容图片和 URL, 再比如
UIActivityViewController
里分享内容的组合和分享目标平台或操作的取舍展示, 等等所以此篇小记录权当是抛砖引玉, 展示这几个功能的简单实现, 如果想实现一些更好的进阶优化, 可以再多看看官方文档, 深入研究
参考链接
- Share
- App Extension Keys
- UIActivityViewController
- SLComposeViewController
App Extensions 篇之 Share Extension
iOS 扩展开发攻略 Share Extension
来源: http://www.jianshu.com/p/83b9debf2890