自分が作りたいアプリのFacebookまわりの事をまとめてみました。
#概要
・Facebookログイン(とログアウト)
・ログインしていない場合、ログインボタンとWelcome画面を表示
・ログインした後(もしくは既にログインしている場合)、名前とユーザ画像、Emailに友達リストをMain画面に表示
・というのを、Swiftで書いてみる
#前提
1.環境
・Xcode 6.4
・Facebook SDK for iOS v4.4.0
・Swift version 1.2
・Facebook API Version 2.4
2.事前準備
・Facebook SDK for iOSのダウンロードとインストール
ここからダウンロードして書類フォルダに解凍しておく
・My Appsの登録(ここから)
登録後にもらえるApp IDとアプリ名をメモっておく
3.注意事項
2015/8/5時点、Xcode,FacebookSDK共に英語ページからダウンロードしています。日本語ページだとちょっと古い…
#作業の流れ
1.Xcode 新規プロジェクトの作成
2.プロジェクトへFacebook SDKを追加
3.AppDelegate.swiftの編集
4.Welcome画面の作成
5.Welcome画面にログイン機能をつける
6.Main画面の作成
7.Welcome画面からMain画面への遷移(既にログイン&ログイン成功)
8.Main画面にFBの情報を表示
9.Main画面にログアウト機能をつける
##1. Xcode 新規プロジェクトの作成
1.1 Xcode を起動して Create a new Xcode project をクリック
1.2 iOS|Application → Single View Application を選択して Next
Product Name: FBLoginSample
Organization Name: 所属組織や自分の名前とか(※とりあえず何でも良い)
Organization Identifier: ドメイン名を逆さにしたもの(※とりあえず何でも良い)
Language: Swift
Devices: iPhone
use CoreData: チェックはずす
1.4 プロジェクトを保存する場所を選択して Create
##2. プロジェクトへFacebook SDKを追加
2.1 書類フォルダからFBSDKCoreKit.frameworkを選択して、ナビゲータの一番上あたりにドロップ
Destination: チェックはずす(とりあえず既定値のまま。チェックしたらプロジェクトフォルダにデータがコピーされる)
Added Forders: Create Groups(とりあえず既定値)
Add to targets: FBloginSample(とりあえず既定値)
ここの設定を変えるとどうなるかとかは、とりあえず脇において既定値のままで。
2.3 FBSDKLoginKit.frameworkも同じようにして追加
プロジェクトのGeneralタブの一番下、Linked Frameworks and Librariesの+ボタンから追加する方法もあります。(むしろそちらが正しいやり方かも??)
2.4 Supporting FilesフォルダのInfo.plistに App ID とアプリ名を登録
FacebookAppID : 事前準備でメモった App ID
FacebookDisplayName :事前準備でメモった アプリ名
URL types | item 0 | URL Schemes | item 0 : fb + App ID
詳しくはFacebook Developer CenterのConfigure the .plist参照
##3.AppDelegate.swiftの編集
3.1 FBSDKCoreKitをimportする
import FBSDKCoreKit
SDK v4.1からimport文だけで使えるようになりました。(一番下のもろもろ参照)
3.2 func applicationとapplicationDidBecomeActiveを編集
func application(application: UIApplication,didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
func application(application: UIApplication,openURL url: NSURL,sourceApplication: String?,annotation: AnyObject?) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
func applicationDidBecomeActive(application: UIApplication) {
FBSDKAppEvents.activateApp()
}
おまじないみたいなモノと思いコピペで。
##4.Welcome画面の作成
4.1 ViewController.swiftをWelcomeViewController.swiftにリネーム
ファイル名の変更にあわせてclass名も変更する
4.2 Main.Storybordを開き View Controllerを選択する。
右パネル identity inspectorを選択し、Custom Classを4.1で編集したWelcomeView Controllerに変更する
##5.Welcome画面にログイン機能をつける
5.1.FBSDKCoreKit, FBSDKLoginKitのインポート記述を追記する
import FBSDKCoreKit
import FBSDKLoginKit
5.2 FBSDKLoginButtonDelegateを追加
5.2.1 WelcomeViewControllerのclass定義にFBSDKLoginButtonDelegateを追加する
class WelcomeViewController: UIViewController, FBSDKLoginButtonDelegate {
5.2.2 func loginButtonとfunc loginButtonDidLogOutを追加する
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//ログインボタンが押された時の処理。Facebookの認証とその結果を取得する
func loginButton(loginButton: FBSDKLoginButton!,didCompleteWithResult
result: FBSDKLoginManagerLoginResult!, error: NSError!) {
println("User Logged In")
if ((error) != nil)
{
//エラー処理
} else if result.isCancelled {
//キャンセルされた時
} else {
//必要な情報が取れていることを確認(今回はemail必須)
if result.grantedPermissions.contains("email")
{
// 次の画面に遷移(後で)
}
}
}
//ログアウトボタンが押された時の処理
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
println("User Logged Out")
}
5.3 ログイン状態のチェック
func viewDidAppearにログイン状態の確認処理を書く。
・ログイン状態の場合→次の画面(この次に作るメイン画面)を表示
・未ログイン状態→ログイン画面を表示して、Facebook認証でログインする
viewDidLoadではないです。viewDidLoadに書くとログインをスキップして次を表示する際にエラー(表示終わっていないのに次の画面呼ぶのはダメよ…みたいな)がでるので。
override func viewDidAppear(animated: Bool) {
if (FBSDKAccessToken.currentAccessToken() != nil) {
println("User Already Logged In")
//後で既にログインしていた場合の処理(メイン画面へ遷移)を書く
} else {
println("User not Logged In")
let loginView : FBSDKLoginButton = FBSDKLoginButton()
self.view.addSubview(loginView)
loginView.center = self.view.center
loginView.readPermissions = ["public_profile", "email", "user_friends"]
loginView.delegate = self
}
}
5.4 ここで試しに起動してみる。
Login with Facebookボタンが表示される→Facebookログイン画面が表示される→(メールアドレスとパスワードを入力する。開発登録していないユーザで入るとエラーになる)→情報へのアクセス許可画面→(ログイン)→ログアウトボタンが表示される→ログアウト→はじめに戻る
##6.Main画面の作成
6.1 ログインした後、遷移させる画面を作る。Main.Storybordを開き、ViewControllerをキャンバス上にドラッグ&ドロップする
6.2 作ったViewControllerにFacebookから取得した情報を表示するコンポーネントを追加。
Identity Inspectorを選択しRestracion IDを入力する
Label : Welcome(固定値)
UIImageView : userImage (プロフィール写真用)
Label : currentUserName(名前を表示する用)
Label : currentUserEmail(emailを表示する用)
Button : Logout(ログアウトボタン)
##7.Welcome画面からMain画面への遷移(既にログイン&ログイン成功)
7.1 segueを作る
WelcomeViewControllerを選択し、Controlキーを押しながらMain画面をクリックする(開発を始めた頃、Commandキーを押しながらSegueを作ろうとして指定された通りに線が出ないんだけど!と悩んだのは内緒です)
Segueの選択画面が表示されるので present modally を選択する
SegueのAttiributes Inspectorを選択し、Identifierを入力する
Identifier : ShowMain
7.2 Welcome画面からの遷移を記述する。
起動した時に既にログインしていた場合と、ログイン画面から問題なく認証できた場合に飛ぶ部分を書く。具体的には、5.2.2の「// 次の画面に遷移(後で)」と、5.3の「//後で既にログインしていた場合の処理(メイン画面へ遷移)を書く」のコメント行をperformSegueWithIdentifierで遷移するように書き換える
override func viewDidAppear(animated: Bool) {
if (FBSDKAccessToken.currentAccessToken() != nil) {
println("User Already Logged In")
self.performSegueWithIdentifier("showMain", sender: self)
...
...
if result.grantedPermissions.contains("email"){
self.performSegueWithIdentifier("showMain", sender: self)
}
...
##8.Main画面にFBの情報を表示する
8.1 MainViewController.swiftを新規作成し、6.1で作ったViewControllerに紐付ける
8.2 FBSDKCoreKit, FBSDKLoginKitのインポート記述を追記する
import FBSDKCoreKit
import FBSDKLoginKit
8.3 写真用のイメージと名前とemailをMainViewController.swiftで使えるようにする。
Main.StoryboardのUIImageを選択し、Controlキーを押しながらMainViewController.Swiftの上にドロップ。
ダイアログが表示されるので、Connectionを設定する。名前とemailも同様に。
結果として、この3行がMainViewController.swiftに追加される
@IBOutlet weak var currentUserName: UILabel!
@IBOutlet weak var currentUserEmail: UILabel!
@IBOutlet weak var userImage: UIImageView!
8.4 FBから取得してきたデータを格納するフィールドを宣言
@IBOutlet weak var currentUserName: UILabel!
@IBOutlet weak var currentUserEmail: UILabel!
@IBOutlet weak var userImage: UIImageView!
var userProfile : NSDictionary!
8.5 画面表示時(viewDidLoad)に、FBからデータ取ってきて表示する(returnUserData)
override func viewDidLoad() {
super.viewDidLoad()
returnUserData()
}
func returnUserData()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me",
parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// エラー処理
println("Error: \(error)")
}
else
{
// プロフィール情報をディクショナリに入れる
self.userProfile = result as! NSDictionary
println(self.userProfile)
// プロフィール画像の取得(よくあるように角を丸くする)
let profileImageURL : String = self.userProfile.objectForKey("picture")?.objectForKey("data")?.objectForKey("url") as! String
var profileImage = UIImage(data: NSData(contentsOfURL: NSURL(string: profileImageURL)!)!)
self.userImage.clipsToBounds = true
self.userImage.layer.cornerRadius = 60
self.userImage.image = self.trimPicture(profileImage!)
//名前とemail
self.currentUserName.text = self.userProfile.objectForKey("name") as? String
self.currentUserEmail.text = self.userProfile.objectForKey("email") as? String
}
})
}
func trimPicture(rawPic:UIImage) -> UIImage {
var rawImageW = rawPic.size.width
var rawImageH = rawPic.size.height
var posX = (rawImageW - 200) / 2
var posY = (rawImageH - 200) / 2
var trimArea : CGRect = CGRectMake(posX, posY, 200, 200)
var rawImageRef:CGImageRef = rawPic.CGImage
var trimmedImageRef = CGImageCreateWithImageInRect(rawImageRef, trimArea)
var trimmedImage : UIImage = UIImage(CGImage : trimmedImageRef)!
return trimmedImage
}
Facebook API Version 2.3までは、parametersを細かく指定しなくてもemailは取得できていたみたいですが、2.4から個別に書かないとダメになりました。IDと名前しか戻ってきません。
##9.Main画面にログアウト機能をつける(成功したらWelcome画面に戻る)
Main.StoryboardのLogoutボタンを選択し、Controlキーを押しながらMainViewController.Swiftの上にドロップ。ダイアログが表示されるので、Accionを設定する。
connectionの設定の部分をoutletからActionに変更する。これも引っかかりました…。
@IBAction func logout(sender: AnyObject) {
let loginManager : FBSDKLoginManager = FBSDKLoginManager()
loginManager.logOut()
self.dismissViewControllerAnimated(true, completion: nil)
}
##10.完成!
#もろもろ
・最新のFacebook SDK v4.1からSwiftがネイティブサポートされ、Bridging headerが不要になりました。(=swiftに直接使うライブラリをimportすればOK)
・Facebookの仕様変更で、アプリを利用している友達しか一覧が取れません。多少の裏技はあるみたいですが、正攻法では難しいみたいです。確認するためには開発仲間を巻き込みましょう……。Sunday In The Parkさんの記事が大変参考になりました。で、作っても友達が表示されないので今回は実装をスキップしました。
・作ったものはGithubに置きました。実行前にFacebookSDKをプロジェクトに追加してください。
・間違ってるとか、こっちの方が良いんじゃ?などの指摘ツッコミ大歓迎。画面がチラチラするのが気になるので誰か良い方法教えてくださいm(__)m