-
-
Save numbbbbb/be5c0200b16d9c5578cd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Beginner’s Guide: Using Social Framework and UIActivityViewController | |
[原文地址](http://www.appcoda.com/social-framework-introduction/) | |
在你即将完成你的一个大型的应用,或者你的boss或客户找到你的时候,你才意识到你的应用还缺少一个重要的需求:分享到Facebook或Twitter。即将到了最后的期限,花费了无数的时间坐在电脑前去去找集成到 Facebook 或者 Twitter 的 SDK,最后发现要实现这个功能实在是太难了,或者几乎是不可能实现。这时,你该怎么办呢?也许可以考虑下是不是可以想一些借口去告诉你的老板或者客户你不准备发布这个 app 了?着急的满头大汗或者不知所措?然而:现在有一个简单快捷的方法让你的应用在短时间内集成分享功能。 | |
亲爱的读者,上面我说的这种糟糕的情况,希望你们没有遇到过。不过确实存在一种完美快捷的方法解决这个问题。事实上:iOS 内置的 SDK 中称这个解决方案为:Social framework。也许,你们好多人已经使用过这个框架,但是,我猜现在依然有一大部分的开发人员还没有注意到这个框架,更不知道使用这个框架在几分钟内就可以把分享功能集成到你的 app 中。 | |
正如我们所了解的,Apple 很久之前就提供了这个内置的方法去分享到 FaceBook 和 Twitter。很显然,集成基本分享功能非常简单,但是想要 集成一些高级的功能则需要使用一些其他合适的 SDK。在这个教程中,我们关注的是使用基本的放方法,更确切的说,我们关注的是如何在我们的应用中使用内置的发送功能去进行分享。在下面的 demo 中,我们仅仅使用了 Socail framework 默认的发送控制器,一些其他的任务 iOS 会帮我们处理。我们也不会去处理类似于登录,获取权限,自定义视图这些细节问题... 简单来说,我们将要做的是在“black box”上添加一些代码。 | |
下一步,我们将讨论一个特殊的视图控制器:**UIActivityViewController**,你也许没听说过,但是一定看到过。 | |
<img src='Images/t42_1_activityVCSimulator .png'> | |
使用这个控制器,你不仅可以使用内置的分享选项啊,也可以使用一些其他的功能:发 e-mail,发短信,打印等等... 事实上,这是一个很容易控制的工具,弹出的选项完全取决于你。毫不夸张的说,把这个工具集成到你的 app 中不会超过两行代码,一会你就会见证这个过程。 | |
如果你很想看看上述的工作如何的实现,并且想在你的下一个 app 中使用。那么,读下去,你会发现这是一个简单而实用的功能。为了让所有的开发人员更加的灵活的使用,这里我没有使用最新的 iOS 8。那么,让我们开始吧。 | |
## 快速预览示例程序 | |
教程中创建的示例程序非常简单。仅仅包含一个控制器(我们使用了 Xcode默认创建的),这个控制器上包含了两部分:顶部一个包含了 button item 的 toolBar, toolBar正下方有一个 textView。这就像一个记笔记的应用的一部分:提供了一个 textView去编写文本,然后发布到 faceBook 和 Twitter,如下图所示: | |
<img src='Images/t42_2_demo_app_sample.png'> | |
toolBar 上的 bar button item 用于弹出一个 action sheet,action sheet显示三个选项 | |
1. share to faceBook | |
2. share to Twitter | |
3. more | |
对于上面的两项我们将使用 social framework来实现:弹出iOS内置的视图控制器去写一些文字,然后发送出去。第三个选项,我们会显示一个**UIActivityViewController**,上边的两项也会显示到这个控制器上边。 | |
<img src='Images/t42_3_demo_app_sample_2.png'> | |
下一个截图展示了iOS提供的默认的在 Twitter 上的发送文字视图: | |
<img src='Images/t42_4_twitter_post.png'> | |
还有一点我必须要提到的就是:在运行程序之前,必须在你的设备的设置选项中登录 facebook或者 Twitter。下边的教程中我会展示如何去操作,但是现在你要记下这件事。当然,在我们的代码中我会考虑到用户没有登录的情况,这种情况下还会给出合理的警告信息。所有的一切会在下面实现。 | |
你也意识到了这不是一个复杂的程序,所以这次我不会给出如何启动Xcode的步骤。我们将在五分钟内做好准备工作并且添加分享选项。然而,对于那些想直接阅读如何实现并且测试示例程序的读者,你可以选择直接在教程的最后去下载示例代码 | |
##创建程序和 UI | |
让我们运行 Xcode 来创建一个工程,创建程序的时候,确保以下选项 | |
* 创建一个Single-View Application | |
* 命名为 EasyShare(可以选择其他的名称) | |
* 选择 swift 开发语言 | |
* 选择设备为iPhone | |
一旦 Xcode 加载完毕,直接去 Interface Builde(Main.storyboard)中的唯一的一个 scene 中去操作。第一步,在状态栏的正下方添加一个 toolBar(Y=20)。你也可以设置一个颜色。在我的示例程序中使用的颜色是 #F39C12。然后,在 toolBar 右方上添加一个 button item(在 Xcode 7.1测试中,toolBar上默认的有一个 button item,因此,可以不用额外的添加),在属性选择栏中可以把 button item 的identifier设置为Action,并且设置为白色。 | |
下一步,在对象库(控件选择栏)中选择一个 UITextView 添加到 scene(Main.storyboard) 上。设置 frame 为如下所示 : | |
* X = 10 | |
* Y= 74 | |
* Width = 580 | |
* Height = 300 | |
下面我们会添加为 textView 添加边框和圆角效果,不过现在做到这已经可以了。不要忘记删除了 textView 中默认提供的“Lorem ipsum” | |
现在我们添加约束。由于我们添加的子控件足够的简单,因此添加约束也是相当的容易。直接添加就可以了,不过有时可能会遇到约束冲突的情况,下面的截图展示了我添加的约束。 | |
下面是 toolbar 的约束: | |
<img src='Images/t42_5_constraints_toolbar.png'> | |
下面是 textView 的约束: | |
<img src='Images/t42_6_constraints_textview.png'> | |
最终,你的 scene 应该是这样的: | |
<img src='Images/t42_7_scene_ib.png'> | |
现在,我们可以连接 textView 的 IBOutlet属性和 toolBar 上 button item 的 IBAction 方法了,在ViewController.swift 这个类中的最上当添加下代码: | |
~~~swift | |
@IBOutlet weak var noteTextview: UITextView! | |
~~~ | |
连接这个属性到 textView 上。然后可以把下面的方法连接到 button item 上: | |
~~~swift | |
@IBAction func showShareOptions(sender: AnyObject) { | |
} | |
~~~ | |
下面我们的很多的工作都会在这个方法中完成,但是目前我们先做到这。 | |
我们已经完成了一些最基本的代码,现在我们在 ViewController 中添加一个自定义方法为 textView 添加边框和圆角效果: | |
~~~swift | |
func configureNoteTextView() { | |
noteTextview.layer.cornerRadius = 8.0 | |
noteTextview.layer.borderColor = UIColor(white: 0.75, alpha: 0.5).CGColor | |
noteTextview.layer.borderWidth = 1.2 | |
} | |
~~~ | |
第一行代码是产生圆角效果,下面两行分别是设置边框的颜色和边框的宽度。 | |
在 viewDidLoad() 方法中进行调用: | |
~~~swift | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
configureNoteTextView() | |
} | |
~~~ | |
最后,我们在工程中添加要使用到的框架(Social framework)。在工程导航栏中单击工程,然后选择 General 选项,滚动到Linked Frameworks and Libraries,点击加号按钮(+),在弹出的窗口中输入“social”进行搜索,选中添加: | |
<img src='Images/t42_8_select_framework.png'> | |
添加成功后Linked Frameworks and Libraries 的结果如下图: | |
<img src='Images/t42_9_linked_framework.png'> | |
下一步,在 ViewController.swift中的最上边添加: | |
~~~ | |
import Social | |
~~~ | |
现在我们的准备工作已经完成了,等下会添加具体的实现功能。你可以先运行一下程序,运行的结果应该如下所示: | |
<img src='Images/t42_2_demo_app_sample.png'> | |
##显示分享选项 | |
在示例程序中,当点击 action bar button 后,我们提供的分享选项会在一个 action sheet 中显示。因此我们可以提前创建showShareOptions(_:) IBAction 方法,下面的截图展示了完成后的效果: | |
<img src ='Images/t42_3_demo_app_sample_2.png'> | |
让我们开始写代码,首先,我们需要考虑到键盘。当 textView 处于编辑状态的时候,如果点击 bar button item,在弹出 action sheet 之前需要隐藏键盘: | |
~~~swift | |
@IBAction func showShareOptions(sender: AnyObject) { | |
// Dismiss the keyboard if it's visible. | |
if noteTextview.isFirstResponder() { | |
noteTextview.resignFirstResponder() | |
} | |
} | |
~~~ | |
现在我们需要初始化一个新的alert controller并且设置具体的样式: | |
~~~swift | |
@IBAction func showShareOptions(sender: AnyObject) { | |
... | |
let actionSheet = UIAlertController(title: "", message: "Share your Note", preferredStyle: UIAlertControllerStyle.ActionSheet) | |
} | |
~~~ | |
上边我们已经提到,在我们的 action sheet 中我们需要显示三个相同的选项。然而,不要忘记为用用户提供一个可以取消 action sheet 的选项,所以,我们一共需要四个选项,代码如下: | |
~~~swift | |
@IBAction func showShareOptions(sender: AnyObject) { | |
... | |
// Configure a new action for sharing the note in Twitter. | |
let tweetAction = UIAlertAction(title: "Share on Twitter", style: UIAlertActionStyle.Default) { (action) -> Void in | |
} | |
// Configure a new action to share on Facebook. | |
let facebookPostAction = UIAlertAction(title: "Share on Facebook", style: UIAlertActionStyle.Default) { (action) -> Void in | |
} | |
// Configure a new action to show the UIActivityViewController | |
let moreAction = UIAlertAction(title: "More", style: UIAlertActionStyle.Default) { (action) -> Void in | |
} | |
let dismissAction = UIAlertAction(title: "Close", style: UIAlertActionStyle.Cancel) { (action) -> Void in | |
} | |
actionSheet.addAction(tweetAction) | |
actionSheet.addAction(facebookPostAction) | |
actionSheet.addAction(moreAction) | |
actionSheet.addAction(dismissAction) | |
presentViewController(actionSheet, animated: true, completion: nil) | |
} | |
~~~ | |
正如你看到的,我们已经成功的显示了 action sheet。现在你可以运行程序然后点击 bar button item 去显示 action sheet。但是现在没有实现业务逻辑,下一部分,我们会逐渐完成缺失的代码让我们的程序可以分享到 Twitter,然后是 facebook。 | |
##Twitter, Twitter | |
上面我已经提到了,如果想要实现分享功能,需要先登录对应的账号。那么,在我们弹出发送视图区实现发送逻辑之前,我们首先检查用户是否已经登录了对应的账号,如果没有登录,我们就要展示一个自定义的视图去提醒用户。 | |
我们首先实现发送到 Twitter 这个功能,一次我们需要检查用户是否已经登录的 Twitter 的账号,下面的是实现 tweetAction 弹出视图的代码: | |
~~~swift | |
let tweetAction = UIAlertAction(title: "Share on Twitter", style: UIAlertActionStyle.Default) { (action) -> Void in | |
// Check if sharing to Twitter is possible. | |
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter) { | |
} | |
else { | |
// 这个方法,下面会给出对应的实现代码 | |
self.showAlertMessage("You are not logged in to your Twitter account.") | |
} | |
} | |
~~~ | |
上面的部分中的SLComposeViewController中的isAvailableForServiceType(_:) 这个类方法可以检查用户是否登录的对应的账号,返回的结果为 true 或 false。这个方法需要传入一个指定的 string 值。Apple 已经为不同的分享方式提供了指定的 string 值,你可以输入**“SLServiceTyp”**,就会自动的提示: | |
<img src='Images/t42_10_service_types.png'> | |
上面你会注意到,用户没有登录时,我们调用了showAlertMessage(_:)方法去提醒用户。但是这个方法现在没有完成,下一部分我们会实现这个方法。但是我需要强调的是虽然这个方法虽然只是通过传入的提醒信息来显示一个警告框,但是,为了我们代码的逻辑更加的清晰,我们最好避免编写完全一样的代码。下面我们也需要使用这个方法来检查用户是否登录了 facebook。 | |
让我们继续,现在我们需要初始化一个SLComposeViewController去弹出一个默认的 view controller来进行发送操作,视图上还会有一个我们想要的“post”按钮。 | |
~~~swift | |
let tweetAction = UIAlertAction(title: "Share on Twitter", style: UIAlertActionStyle.Default) { (action) -> Void in | |
// Check if sharing to Twitter is possible. | |
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter) { | |
// Initialize the default view controller for sharing the post. | |
let twitterComposeVC = SLComposeViewController(forServiceType: SLServiceTypeTwitter) | |
} | |
else { | |
self.showAlertMessage("You are not logged in to your Twitter account.") | |
} | |
} | |
~~~ | |
我们必须要传入对应的分享的类型去初始化SLComposeViewController。 | |
上面的对象中有一个setInitialText(_:)方法可以直接把 textView 中的内容设置到发送视图中。当你明白如实使用这个方法后,你会变得更加的得心应手。但是不要忽略一个问题:发送 Twitter 的时候,发送的文字不能多于140的字符。 | |
下一步我们要做什么?非常简单:首先我们需要使用我之前提到的方法来检查 textView 中的内容是否多于140个字符,如果多于140个字符,我们就取前140个字符。 | |
下面是代码: | |
~~~swift | |
let tweetAction = UIAlertAction(title: "Share on Twitter", style: UIAlertActionStyle.Default) { (action) -> Void in | |
// Check if sharing to Twitter is possible. | |
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter) { | |
// Initialize the default view controller for sharing the post. | |
let twitterComposeVC = SLComposeViewController(forServiceType: SLServiceTypeTwitter) | |
// Set the note text as the default post message. | |
if count(self.noteTextview.text) <= 140 { // iOS 9之后,可以尝试使用if self.noteTextview.text.characters.count >= 140 | |
twitterComposeVC.setInitialText("\(self.noteTextview.text)") | |
} | |
else { | |
let index = advance(self.noteTextview.text.startIndex, 140) | |
let subText = self.noteTextview.text.substringToIndex(index) | |
// iOS9之后,可以尝试 | |
// let index = self.noteTextview.text.startIndex.advancedBy(140) | |
// let subText = self.noteTextview.text.substringToIndex(index) | |
twitterComposeVC.setInitialText("\(subText)") | |
} | |
} | |
else { | |
self.showAlertMessage("You are not logged in to your Twitter account.") | |
} | |
} | |
~~~ | |
不过上面缺少了弹出视图的方法: | |
~~~swift | |
let tweetAction = UIAlertAction(title: "Share on Twitter", style: UIAlertActionStyle.Default) { (action) -> Void in | |
// Check if sharing to Twitter is possible. | |
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter) { | |
... | |
// Display the compose view controller. | |
self.presentViewController(twitterComposeVC, animated: true, completion: nil) | |
} | |
else { | |
self.showAlertMessage("You are not logged in to your Twitter account.") | |
} | |
} | |
~~~ | |
上面我们已经完成了发送 Twitter 的工作。 | |
不过我们还要添加上面缺少的方法: | |
~~~swift | |
func showAlertMessage(message: String!) { | |
let alertController = UIAlertController(title: "EasyShare", message: message, preferredStyle: UIAlertControllerStyle.Alert) | |
alertController.addAction(UIAlertAction(title: "Okay", style: UIAlertActionStyle.Default, handler: nil)) | |
presentViewController(alertController, animated: true, completion: nil) | |
} | |
~~~ | |
最后,正如你看到的,我们已经使用很少的代码去实现了发送文本到 Twitter(facebook 要做的步骤类似)。让我们的程序也可以使用分享到 facebook,在这之前我们可以测试下我们的程序。 | |
##分享到 Facebook | |
这部分,我们需要分享到 facebook, 实现步骤类似于 Twitter。不过,我们现在会更简单一点,因为 facebook 没有对发送的文字长度做限制,我们可以跳过检查长度这个步骤。 | |
现在我们需要关注的是facebookPostAction alert action,下面是我们可以直接来实现,并没有什么需要特别注意的: | |
~~~swift | |
let facebookPostAction = UIAlertAction(title: "Share on Facebook", style: UIAlertActionStyle.Default) { (action) -> Void in | |
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook) { | |
let facebookComposeVC = SLComposeViewController(forServiceType: SLServiceTypeFacebook) | |
facebookComposeVC.setInitialText("\(self.noteTextview.text)") | |
self.presentViewController(facebookComposeVC, animated: true, completion: nil) | |
} | |
else { | |
self.showAlertMessage("You are not connected to your Facebook account.") | |
} | |
} | |
~~~ | |
我们依然需要检查用户是否登录的 facebook 的账户,对于SLComposeViewController的初始化,我们需要传入facebook 对应的 string 的值。把 textView 中的文字设置为发送的内容,最后,用户没有登录 facebook 时,我们依然可以展示一个没有登录的提醒信息。 | |
##开始测试 | |
我们的示例程序可以在模拟器和真机上进行测试。在测试之前,你需要成功的登录对应的账号,否则,你会看到的如下图所示: | |
<img src='Images/t42_11_twitter_no_connection.png'> | |
你可以打开设备的设置界面进行账号的登录,你可以看到如下图所示: | |
<img src='Images/t42_13_settings_both.png'> | |
如果想登录 Twitter,可以选择 Twitter 这个选项,然后输入账号和密码,然后登录: | |
<img src='Images/t42_14_twitter_filled_in.png'> | |
登录成功后,界面会多了一个显示用户名的行(可以用来更改密码和注销账号): | |
<img src='Images/t42_15_twitter_logged_in.png'> | |
可以使用同样的方法登录 facebook,只需要提供 email 和密码就可以了,你也可以在这个界面上进行注销操作。 | |
<img src='Images/t42_16_facebook_logged_in.png'> | |
确保你已经登录的这两个账号,登录成功后,就可以尽情的测试你的程序了。 | |
##使用UIActivityViewController | |
如果想要同时添加多个分享选项,或者集成一些额外的分享功能,UIActivityViewController提供了一个很好的解决方案。这些选项取决于你想要展示的内容,下面是一些常用的选项: | |
* Send an email | |
* Send a SMS | |
* Share on Twitter and Facebook | |
* Add to Reading List | |
* Copy | |
* Send using AirDrop | |
下面你看到是仅仅通过两行代码去初始化和使用UIActivityViewController。初始化这个方法需要传入两个参数,第二个是可选的,你可以设置为 nil。 | |
第一个参数是一个数组,里面包含了我们想要发送的内容。在我们的示例程序中,我们在数组中添加了 textView 中的文字。当然了,我们也可以把图片添加到数组中,数组中的内容决定了系统显示的样式。具体来说,如果我们只有一张图片,那么就没有必要添加“Add to reading list”。 | |
第二个参数也是一个数组。通过这个数组你可以明确的告诉系统你想显示的activities的类型。如果设置为 nil,那么系统会显示所有的可以使用的activities视图控制器。 | |
我们一会再看如何移除选项,但是现在我们要关注的是第三个选项:moreAction。下面我们会初始化UIActivityViewController然后显示出来: | |
~~~swift | |
let moreAction = UIAlertAction(title: "More", style: UIAlertActionStyle.Default) { (action) -> Void in | |
let activityViewController = UIActivityViewController(activityItems: [self.noteTextview.text], applicationActivities: nil) | |
self.presentViewController(activityViewController, animated: true, completion: nil) | |
} | |
~~~ | |
如果运行程序,现在 More 选项已经可以使用了,不过模拟器上的选项可能会没有真机上多,例如,模拟器上就没有发送 SMS 选项: | |
<img src='Images/t42_1_activityVCSimulator.png'> | |
上面我们已经提到,有的开发者需要移除一些选项。移除选项你可能需要这个属性:excludedActivityTypes,你所要做的就是传入你不想集成到你的项目中的属性。我已经更新了代码,你可以看到,现在多了一行,这行代码可以移除发送邮件这个选项: | |
~~~swift | |
let moreAction = UIAlertAction(title: "More", style: UIAlertActionStyle.Default) { (action) -> Void in | |
let activityViewController = UIActivityViewController(activityItems: [self.noteTextview.text], applicationActivities: nil) | |
activityViewController.excludedActivityTypes = [UIActivityTypeMail] | |
self.presentViewController(activityViewController, animated: true, completion: nil) | |
} | |
~~~ | |
在此运行程序,你会发现现在发送邮件选项已经不见了 | |
<img src="Images/t42_18_missing_email_button.png"> | |
##总结 | |
作为一个开发者,我必须承认的是,当我第一次使用示例程序中的分享功能的时候,我感到非常惊讶,因为集成这些功能真是太简单了。毫无疑问,我们今天解决的只是一些简单的编程任务,不过我还是希望实现这些功能的步骤我已经阐述的足够明白。显然,无论是iOS 提供的内置的功能还是UIActivityViewController并不是适用于所有的情况。因为这些系统控件可能和我们的自定义的 UI 不匹配,但是如果不存在 UI 的情况,那么就可以考虑下使用系统方案。如果你已经准备使用了,那么现在你已经知道如何几分钟内集成这些功能了。无论你是否决定使用今天我所讲的内容,我都希望今天的内容可以为你以后的开发中带来方便。 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment