Xamarin.iOS 中的社交框架
社交框架提供统一的 API,用于与 Twitter、Facebook 以及中国用户的新浪微博等社交网络交互。
使用社交框架,应用程序可以通过单个 API 与社交网络交互,而无需管理身份验证。 它包括一个系统提供的用于撰写帖子的视图控制器,以及允许通过 HTTP 使用每个社交网络的 API 的抽象层。
连接到 Twitter
Twitter 帐户设置
要使用社交框架连接到 Twitter,需要在设备设置中配置帐户,如下所示:
使用 Twitter 输入并验证帐户后,使用社交框架类访问 Twitter 的设备上的任何应用程序都将使用此帐户。
发送推文
社交框架包括一个名为 SLComposeViewController
的控制器,可提供系统提供的视图来编辑和发送推文。 以下屏幕截图显示了此视图的示例:
要将 SLComposeViewController
与 Twitter 一起使用,必须通过使用 SLServiceType.Twitter
调用 FromService
方法来创建控制器实例,如下所示:
var slComposer = SLComposeViewController.FromService (SLServiceType.Twitter);
返回 SLComposeViewController
实例后,它可用于显示要发布到 Twitter 的 UI。 但首先请通过调用 IsAvailable
来检查社交网络(在本例中为 Twitter)的可用性:
if (SLComposeViewController.IsAvailable (SLServiceKind.Twitter)) {
...
}
SLComposeViewController
无需用户交互即可直接发送推文。 但可以使用以下方法对它进行初始化处理:
SetInitialText
- 添加要在推文中显示的初始文本。AddUrl
- 向推文添加 URL。AddImage
- 将图像添加到推文中。
初始化后,调用 PresentVIewController
将会显示由 SLComposeViewController
创建的视图。 然后,用户可以选择性编辑和发送推文,或取消发送推文。 在任一情况下,控制器都应在 CompletionHandler
中被关闭,并且在此处还可以检查结果,以查看是否发送推文或取消了推文,如下所示:
slComposer.CompletionHandler += (result) => {
InvokeOnMainThread (() => {
DismissViewController (true, null);
resultsTextView.Text = result.ToString ();
});
};
推文示例
以下代码演示如何使用 SLComposeViewController
显示用于发送推文的视图:
using System;
using Social;
using UIKit;
namespace SocialFrameworkDemo
{
public partial class ViewController : UIViewController
{
#region Private Variables
private SLComposeViewController _twitterComposer = SLComposeViewController.FromService (SLServiceType.Twitter);
#endregion
#region Computed Properties
public bool isTwitterAvailable {
get { return SLComposeViewController.IsAvailable (SLServiceKind.Twitter); }
}
public SLComposeViewController TwitterComposer {
get { return _twitterComposer; }
}
#endregion
#region Constructors
protected ViewController (IntPtr handle) : base (handle)
{
}
#endregion
#region Override Methods
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
// Update UI based on state
SendTweet.Enabled = isTwitterAvailable;
}
#endregion
#region Actions
partial void SendTweet_TouchUpInside (UIButton sender)
{
// Set initial message
TwitterComposer.SetInitialText ("Hello Twitter!");
TwitterComposer.AddImage (UIImage.FromFile ("Icon.png"));
TwitterComposer.CompletionHandler += (result) => {
InvokeOnMainThread (() => {
DismissViewController (true, null);
Console.WriteLine ("Results: {0}", result);
});
};
// Display controller
PresentViewController (TwitterComposer, true, null);
}
#endregion
}
}
调用 Twitter API
社交框架还包括对于向社交网络发出 HTTP 请求的支持。 它将请求封装在用于面向特定社交网络 API 的 SLRequest
类中。
例如,以下代码会向 Twitter 发出获取公共时间线的请求(通过扩展上述代码):
using Accounts;
...
#region Private Variables
private ACAccount _twitterAccount;
#endregion
#region Computed Properties
public ACAccount TwitterAccount {
get { return _twitterAccount; }
}
#endregion
#region Override Methods
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
// Update UI based on state
SendTweet.Enabled = isTwitterAvailable;
RequestTwitterTimeline.Enabled = false;
// Initialize Twitter Account access
var accountStore = new ACAccountStore ();
var accountType = accountStore.FindAccountType (ACAccountType.Twitter);
// Request access to Twitter account
accountStore.RequestAccess (accountType, (granted, error) => {
// Allowed by user?
if (granted) {
// Get account
_twitterAccount = accountStore.Accounts [accountStore.Accounts.Length - 1];
InvokeOnMainThread (() => {
// Update UI
RequestTwitterTimeline.Enabled = true;
});
}
});
}
#endregion
#region Actions
partial void RequestTwitterTimeline_TouchUpInside (UIButton sender)
{
// Initialize request
var parameters = new NSDictionary ();
var url = new NSUrl("https://api.twitter.com/1.1/statuses/user_timeline.json?count=10");
var request = SLRequest.Create (SLServiceKind.Twitter, SLRequestMethod.Get, url, parameters);
// Request data
request.Account = TwitterAccount;
request.PerformRequest ((data, response, error) => {
// Was there an error?
if (error == null) {
// Was the request successful?
if (response.StatusCode == 200) {
// Yes, display it
InvokeOnMainThread (() => {
Results.Text = data.ToString ();
});
} else {
// No, display error
InvokeOnMainThread (() => {
Results.Text = string.Format ("Error: {0}", response.StatusCode);
});
}
} else {
// No, display error
InvokeOnMainThread (() => {
Results.Text = string.Format ("Error: {0}", error);
});
}
});
}
#endregion
我们来仔细查看此代码。 首先,它会获取对帐户存储的访问权限,并获取 Twitter 帐户的类型:
var accountStore = new ACAccountStore ();
var accountType = accountStore.FindAccountType (ACAccountType.Twitter);
接下来,它会询问用户其应用是否可以访问其 Twitter 帐户,如果已授予访问权限,该帐户将会加载到内存中并更新 UI:
// Request access to Twitter account
accountStore.RequestAccess (accountType, (granted, error) => {
// Allowed by user?
if (granted) {
// Get account
_twitterAccount = accountStore.Accounts [accountStore.Accounts.Length - 1];
InvokeOnMainThread (() => {
// Update UI
RequestTwitterTimeline.Enabled = true;
});
}
});
当用户请求时间线数据(通过点击 UI 中的按钮)时,应用会首先形成从 Twitter 访问数据的请求:
// Initialize request
var parameters = new NSDictionary ();
var url = new NSUrl("https://api.twitter.com/1.1/statuses/user_timeline.json?count=10");
var request = SLRequest.Create (SLServiceKind.Twitter, SLRequestMethod.Get, url, parameters);
此示例通过在 URL 中包含 ?count=10
将返回的结果限制为最后 10 个条目。 最后,它将请求附加到 Twitter 帐户(已在上面加载)并执行对 Twitter 的调用来提取数据:
// Request data
request.Account = TwitterAccount;
request.PerformRequest ((data, response, error) => {
// Was there an error?
if (error == null) {
// Was the request successful?
if (response.StatusCode == 200) {
// Yes, display it
InvokeOnMainThread (() => {
Results.Text = data.ToString ();
});
} else {
// No, display error
InvokeOnMainThread (() => {
Results.Text = string.Format ("Error: {0}", response.StatusCode);
});
}
} else {
// No, display error
InvokeOnMainThread (() => {
Results.Text = string.Format ("Error: {0}", error);
});
}
});
如果成功加载数据,将会显示原始 JSON 数据(如以下示例输出所示):
在实际应用中,可以按正常方式分析 JSON 结果,并将结果呈现给用户。 有关如何分析 JSON 的信息,请参阅 Web 服务简介。
连接到 Facebook
Facebook 帐户设置
使用社交框架连接到 Facebook 与上文所述的用于 Twitter 的过程几乎相同。 必须在设备设置中配置 Facebook 用户帐户,如下所示:
配置后,使用社交框架的设备上的任何应用程序都将使用此帐户连接到 Facebook。
发布到 Facebook
由于社交框架是一个旨在访问多个社交网络的统一的 API,,因此无论使用哪个社交网络,该代码都几乎完全相同。
例如,可以像前面所示的 Twitter 示例中一样使用 SLComposeViewController
,唯一不同的是切换到特定于 Facebook 的设置和选项。 例如:
using System;
using Foundation;
using Social;
using UIKit;
namespace SocialFrameworkDemo
{
public partial class ViewController : UIViewController
{
#region Private Variables
private SLComposeViewController _facebookComposer = SLComposeViewController.FromService (SLServiceType.Facebook);
#endregion
#region Computed Properties
public bool isFacebookAvailable {
get { return SLComposeViewController.IsAvailable (SLServiceKind.Facebook); }
}
public SLComposeViewController FacebookComposer {
get { return _facebookComposer; }
}
#endregion
#region Constructors
protected ViewController (IntPtr handle) : base (handle)
{
}
#endregion
#region Override Methods
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
// Update UI based on state
PostToFacebook.Enabled = isFacebookAvailable;
}
#endregion
#region Actions
partial void PostToFacebook_TouchUpInside (UIButton sender)
{
// Set initial message
FacebookComposer.SetInitialText ("Hello Facebook!");
FacebookComposer.AddImage (UIImage.FromFile ("Icon.png"));
FacebookComposer.CompletionHandler += (result) => {
InvokeOnMainThread (() => {
DismissViewController (true, null);
Console.WriteLine ("Results: {0}", result);
});
};
// Display controller
PresentViewController (FacebookComposer, true, null);
}
#endregion
}
}
在用于 Facebook 时,SLComposeViewController
将显示与 Twitter 示例外观几乎完全相同的视图,在本例中会显示 Facebook 作为标题:
调用 Facebook 图形 API
与 Twitter 示例类似,社交网络的 SLRequest
对象也可与 Facebook 的图形 API 一起使用。 例如,以下代码会从图形 API 中返回有关 Xamarin 帐户的信息(通过扩展上述代码):
using Accounts;
...
#region Private Variables
private ACAccount _facebookAccount;
#endregion
#region Computed Properties
public ACAccount FacebookAccount {
get { return _facebookAccount; }
}
#endregion
#region Override Methods
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
// Update UI based on state
PostToFacebook.Enabled = isFacebookAvailable;
RequestFacebookTimeline.Enabled = false;
// Initialize Facebook Account access
var accountStore = new ACAccountStore ();
var options = new AccountStoreOptions ();
var options.FacebookAppId = ""; // Enter your specific Facebook App ID here
accountType = accountStore.FindAccountType (ACAccountType.Facebook);
// Request access to Facebook account
accountStore.RequestAccess (accountType, options, (granted, error) => {
// Allowed by user?
if (granted) {
// Get account
_facebookAccount = accountStore.Accounts [accountStore.Accounts.Length - 1];
InvokeOnMainThread (() => {
// Update UI
RequestFacebookTimeline.Enabled = true;
});
}
});
}
#endregion
#region Actions
partial void RequestFacebookTimeline_TouchUpInside (UIButton sender)
{
// Initialize request
var parameters = new NSDictionary ();
var url = new NSUrl ("https://graph.facebook.com/283148898401104");
var request = SLRequest.Create (SLServiceKind.Facebook, SLRequestMethod.Get, url, parameters);
// Request data
request.Account = FacebookAccount;
request.PerformRequest ((data, response, error) => {
// Was there an error?
if (error == null) {
// Was the request successful?
if (response.StatusCode == 200) {
// Yes, display it
InvokeOnMainThread (() => {
Results.Text = data.ToString ();
});
} else {
// No, display error
InvokeOnMainThread (() => {
Results.Text = string.Format ("Error: {0}", response.StatusCode);
});
}
} else {
// No, display error
InvokeOnMainThread (() => {
Results.Text = string.Format ("Error: {0}", error);
});
}
});
}
#endregion
此代码与上面显示的 Twitter 版本的唯一真正的区别在于 Facebook 要求获取开发人员/应用特定的 ID(可以从 Facebook 的开发人员门户生成),并且必须在发出请求时将其设置为选项:
var options = new AccountStoreOptions ();
var options.FacebookAppId = ""; // Enter your specific Facebook App ID here
...
// Request access to Facebook account
accountStore.RequestAccess (accountType, options, (granted, error) => {
...
});
未能设置此选项(或使用无效密钥)将导致错误或不会返回任何数据。
总结
本文介绍了如何使用社交框架与 Twitter 和 Facebook 进行交互。 其中显示了在设备设置中为每个社交网络配置帐户的位置。 此外,还讨论了如何使用 SLComposeViewController
来呈现发布到社交网络的统一视图。 此外,它还介绍了用于调用每个社交网络 API 的 SLRequest
类。