Xamarin.iOS 中的社交架構

社交架構提供統一的 API,可與 Twitter 和 Facebook 等社交網路互動,以及中國使用者的新浪威博。

使用 Social Framework 可讓應用程式從單一 API 與社交網路互動,而不需要管理驗證。 它包含一個系統提供的檢視控制器來撰寫文章,以及一個抽象概念,允許透過 HTTP 取用每個社交網路的 API。

連線 推特

Twitter 帳戶 設定

若要使用Social Framework連線到 Twitter,必須在裝置設定中設定帳戶,如下所示:

Twitter Account Settings

一旦使用 Twitter 輸入並驗證帳戶之後,使用 Social Framework 類別存取 Twitter 的裝置上的任何應用程式都會使用此帳戶。

傳送推文

社交架構包含稱為 SLComposeViewController 的控制器,其提供用於編輯和傳送推文的系統檢視。 下列螢幕快照顯示此檢視的範例:

This screenshot shows an example of the SLComposeViewController

若要搭配 Twitter 使用 SLComposeViewController ,必須藉由呼叫 FromService 方法 SLServiceType.Twitter 來建立控制器的實例,如下所示:

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 要求。 它會將要求封裝在類別中 SLRequest ,以特定社交網路的 API 為目標。

例如,下列程式代碼會要求 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);

此範例會藉由 ?count=10 在 URL 中包含 ,將傳回的結果限制為最後十個專案。 最後,它會將要求附加至 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 資料(如下列範例輸出所示):

An example of the raw JSON data display

在實際的應用程式中,JSON 結果接著可以剖析為一般,並將結果呈現給使用者。 如需如何剖析 JSON 的資訊,請參閱 Web 服務 簡介。

連線 Facebook

Facebook 帳戶 設定

使用社交架構向Facebook連線與上面所示 Twitter所使用的程式幾乎完全相同。 Facebook 使用者帳戶必須在裝置設定中設定,如下所示:

Facebook Account Settings

設定之後,使用 Social Framework 之裝置上的任何應用程式都會使用此帳戶來連線到 Facebook。

張貼到Facebook

由於社交架構是一種統一的 API,其設計目的是存取多個社交網路,因此不論使用的社交網路為何,程式代碼都幾乎完全相同。

例如, SLComposeViewController 可以和稍早所示的 Twitter 範例一樣使用 ,唯一不同的是切換至 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 作為標題:

The SLComposeViewController display

呼叫Facebook圖形 API

與 Twitter 範例類似,Social Framework 的物件 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 要求取得開發人員/應用程式特定識別碼(您可以從 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 來呈現發佈至社交網路的統一檢視。 此外,它檢查 SLRequest 了用來呼叫每個社交網路 API 的類別。