#19. FB Login-使用cocoapods安裝套件

先在FB 開發網站建立對應的App

可參考Peter大這篇

設定開發環境

可照著QuickStart的步驟一步一步進行

這邊我結合自己實際上遇到的問題,做個紀錄

  1. 安裝之前先更新Ruby
為何是Ruby?CocoaPods 是基於 Ruby 語言開發而成,每台Mac都有自帶 Ruby 系統。若你本身熟悉 Ruby 語言,那麼 CocoaPods 的 pods 就近乎於 Ruby 的 gems。-以上擷取至https://www.appcoda.com.tw/cocoapods/

打開terminal終端機輸入以下字串

sudo gem update --system

再輸入一次測試,就顯示已經更新到最新版

2. 開始安裝cocoapods

sudo gem install cocoapods

出現以下畫面就安裝成功了!

3.檢查cocoapods安裝版本

pod --version

可到開發者的gitHub比對是否已安裝到最新版本

https://github.com/CocoaPods/CocoaPods

4.打開terminal,輸入專案所在(也可以直接拖曳資料夾)

5.建立Podfile

pod init

此時資料夾會多一個Podfile記事本檔案

6.在Podfile記事本輸入以下字串,大小寫要完全一樣,最後請記得存檔

pod 'FBSDKLoginKit'
pod 'FacebookLogin'

7.回到terminal安裝套件

pod install

安裝之後,專案資料夾會多出以下檔案

8.先關閉原本已經打開的專案,改開啟.xcworkspace,點開之後會發現FB套件已經安裝成功

9.此時就可以開心import FB套件啦!

回到FB iOS SDK官方文件,繼續步驟二

填入Bundle Identifier

在general中可看到Bundle Identifier,將整串直接複製貼上到官方文件的步驟二,記得save

copy
paste

設定info.plist

1.info.plist按右鍵選擇Source Code

2.複製文件中的兩組程式碼

3.轉貼到info.plist中的<dict>…</dict>

記得替換正確資料到<string>APP-ID</string>、<string>CLIENT-TOKEN</string>、<string>APP-NAME</string>

APP-ID

CLIENT-TOKEN

APP-NAME

連結App Delegate

第一組程式複製之後全部取代專案中的AppDelegate程式碼,若是iOS 13的版本,就需要再額外添加第二組程式碼到SceneDelegate

藍色區段是新增的程式碼

設計UI

override func viewDidLoad() {
super.viewDidLoad()
loginConfig()
logoutConfig()
profileImageView.image = UIImage(systemName: "person.crop.square")
}
func loginConfig() {
var configuration = UIButton.Configuration.filled()
configuration.title = "Facebook Login"
configuration.buttonSize = .large
configuration.titleAlignment = .center
configuration.cornerStyle = .capsule
configuration.image = UIImage(systemName: "person.fill", withConfiguration: UIImage.SymbolConfiguration(scale: .large))
configuration.imagePlacement = .trailing
configuration.imagePadding = 15
loginBtn.configuration = configuration
loginBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
}
func logoutConfig() {
var configuration = UIButton.Configuration.gray()
configuration.title = "Log Out"
configuration.buttonSize = .large
configuration.cornerStyle = .capsule
logoutBtn.configuration = configuration
logoutBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
}

設定loginManager

permissions:傳入想要的權限
viewController:呈現資料的controller頁面
closure{}:若沒有取消也沒出現錯誤,就會直接跳到getFacebookData的程式

func login() {
let loginManager = LoginManager()
loginManager.logIn(permissions: ["public_profile","email"], viewController: self) { (result) in
switch result {
case .cancelled:
print("使用者取消登入")
case .failed(let error):
print(error.localizedDescription)
case .success(granted: _, declined: _, token: _):
self.getFacebookData()
}
}
}
@IBAction func fbLogin(_ sender: UIButton) {
self.login()
}

登入成功後取得FB資料

若登入成功,便可透過 FB的Graph API取得個人資料
詳細的Graph API說明可參考下方連結

graphPath: 傳入想要取得的node類型,比如個人頁面、文章、照片…,輸入”me”可以取得已登入者的個人頁面

The /me node is a special endpoint that translates to the object ID of the person or Page whose access token is currently being used to make the API calls.

parameters: node的下一層是fields,fields包含個人頁面的詳細資料

connection:接到Graph API的連線

result:由GraphRequest得到的資料,是以JSON格式寫成

將result轉型成字典後,再抓出name/email/de每個key的value,接著運用URLSession下載profile photo

print(dict)印出的畫面
func getFacebookData() {  if AccessToken.current != nil {
GraphRequest(graphPath: "me", parameters: ["fields":"id,email,name,picture.type(large)"]).start { connection, result, error in
if error == nil {
let dict = result as! [String:AnyObject] as NSDictionary
let id = dict.object(forKey: "id") as! String
let name = dict.object(forKey: "name") as! String
let email = dict.object(forKey: "email") as! String
print("Name: \(name)")
print("Email: \(email)")
print("Id: \(id)")
print(dict)

self.nameLabel.text = name
self.emailLabel.text = email
self.idLabel.text = id
if let profilePicture = dict.object(forKey: "picture") as? [String: Any] {
if let profilePicData = profilePicture["data"] as? [String: Any] {
print("Data: \(profilePicData)")
if let profilePicStr = profilePicData["url"] as? String {
let url = URL(string: profilePicStr)!
print(url)
URLSession.shared.dataTask(with: url) { data, response, error in
print("enter URLSession")
if let data = data,
let image = UIImage(data: data) {
DispatchQueue.main.async {
print("enter main queue")
self.profileImageView.image = image
}
}
}.resume()
}
}
}
self.logoutBtn.isHidden = false
self.loginBtn.isHidden = true
} else {
print(error?.localizedDescription as Any)
}
}
} else {
print("Access Token is NIL")
}

登出

@IBAction func fbLogout(_ sender: UIButton) {
let logout = LoginManager()
logout.logOut()
loginBtn.isHidden = false
logoutBtn.isHidden = true
profileImageView.image = UIImage(systemName: "person.crop.square")
nameLabel.text = ""
emailLabel.text = ""
idLabel.text = ""
}

模擬畫面

遇到問題

運行模擬器之後,過了很久出現以下錯誤訊息

<Warning>: Please set a value for FacebookAutoLogAppEventsEnabled. Set the flag to TRUE if you want to collect app install, app launch and in-app purchase events automatically. To request user consent before collecting data, set the flag value to FALSE, then change to TRUE once user consent is received. Learn more: https://developers.facebook.com/docs/app-events/getting-started-app-events-ios#disable-auto-events.<Warning>: You haven't set a value for FacebookAdvertiserIDCollectionEnabled. Set the flag to TRUE if you want to collect Advertiser ID for better advertising and analytics results. To request user consent before collecting data, set the flag value to FALSE, then change to TRUE once user consent is received. Learn more: https://developers.facebook.com/docs/app-events/getting-started-app-events-ios#disable-auto-events.

解法參考

所以只要將下方程式碼再貼到info.plist的Source Code中即可

<key>FacebookAutoLogAppEventsEnabled</key>
<string>TRUE</string>
<key>FacebookAdvertiserIDCollectionEnabled</key>
<string>TRUE</string>

一陣子沒摸程式,整個思路就會頓頓的,要天天碰才行啊…😨

參考資料

--

--