FacebookSDK(4.1.x) 自定义登录 UI 按钮 - Swift(1.2)
Posted
技术标签:
【中文标题】FacebookSDK(4.1.x) 自定义登录 UI 按钮 - Swift(1.2)【英文标题】:FacebookSDK(4.1.x) Custom Login UI Button - Swift(1.2) 【发布时间】:2015-06-04 03:05:36 【问题描述】:在this tutorial 之后,我设法使 Facebook 登录按钮正常工作。但是,它会自动从 SDK 分配按钮图像,并且无法自定义(因为它不是在 Storyboard 上创建的),因此我无法改用自己的按钮图像或文本。
我相信这部分代码(在 ViewDidLoad 中)正在分配按钮:
let loginView : FBSDKLoginButton = FBSDKLoginButton()
self.view.addSubview(loginView)
loginView.center = self.view.center
loginView.readPermissions = ["public_profile", "email"]
loginView.delegate = self
我需要做的是在 Storyboard 上创建一个 @IBOutlet 按钮并从那里对其进行自定义。我该怎么做?
【问题讨论】:
【参考方案1】:使用自定义按钮和访问令牌登录。
在 facebook sdk 4.x 中获取用户信息
斯威夫特
@IBAction func btnFBLoginPressed(sender: AnyObject)
var fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logInWithReadPermissions(["email"], fromViewController: self, handler: (result, error) -> Void in
if (error == nil)
var fbloginresult : FBSDKLoginManagerLoginResult = result
if(fbloginresult.grantedPermissions.contains("email"))
self.getFBUserData()
fbLoginManager.logOut()
)
func getFBUserData()
if((FBSDKAccessToken.currentAccessToken()) != nil)
FBSDKGraphRequest(graphpath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).startWithCompletionHandler( (connection, result, error) -> Void in
if (error == nil)
println(result)
)
【讨论】:
containsObject 部分给出错误:'Set<NSObject>' does not have a member named 'containsObject'
****找到答案:将 containsObject
更改为 contains
更改代码:if(fbloginresult.grantedPermissions..contains("email") @senty
很好,fbLoginManager.logOut() 是干什么用的?
修改结果检查以避免在 Facebook 对话框显示“您已经授权...”时用户取消而不是确定时出现错误“在展开可选选项时获得 nil”。使用if fbloginresult.grantedPermissions != nil && fbloginresult.grantedPermissions.contains("email")
而不是仅仅尝试查看grantedPermissions 包含电子邮件
截至 2016 年 7 月,logInWithReadPermissions 应包括 viewController。所以将fbLoginManager .logInWithReadPermissions(["email"], handler: (result, error) -> Void in
修改为fbLoginManager.logInWithReadPermissions(permissions, fromViewController: self, handler: (result, error) -> Void in
。检查@SantosRamon 的答案以供参考【参考方案2】:
使用最新的 Facebook SDK (01/05/2016) 和 Swift 2.1 更新了答案
使用 Interface Builder 或通过代码创建一个 UIButton 并将该按钮的操作与此链接:
@IBAction func loginFacebookAction(sender: AnyObject)
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logInWithReadPermissions(["email"], fromViewController: self) (result, error) -> Void in
if (error == nil)
let fbloginresult : FBSDKLoginManagerLoginResult = result
if(fbloginresult.grantedPermissions.contains("email"))
self.getFBUserData()
前面代码的快乐案例触发了函数 self.getFBUserData() 所以你必须在同一个文件中实现该函数
func getFBUserData()
if((FBSDKAccessToken.currentAccessToken()) != nil)
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).startWithCompletionHandler( (connection, result, error) -> Void in
if (error == nil)
//everything works print the user data
print(result)
)
【讨论】:
修改结果检查以避免在 Facebook 对话框显示“您已经授权...”时用户取消而不是确定时出现错误“在展开可选选项时获得 nil”。使用 if fbloginresult.grantedPermissions != nil && fbloginresult.grantedPermissions.contains("email") 而不是仅仅尝试查看grantedPermissions 包含电子邮件【参考方案3】:我在 xcode 7.3 中成功做到了
@IBAction func fbLoginBtnAction(sender: AnyObject)
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logInWithReadPermissions(["email"], fromViewController: self, handler: (result, error) -> Void in
if error == nil
print("Logged in through facebook" )
self.getFBUserData()
else
print("Facebook Login Error----\n",error)
)
func getFBUserData ()
if((FBSDKAccessToken.currentAccessToken()) != nil)
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).startWithCompletionHandler( (connection, result, error) -> Void in
if (error == nil)
print(result)
)
【讨论】:
【参考方案4】:可重用类 (Swift 4)。
用法:FacebookSignIn.shared.signIn(from: yourVC, completion: yourCompletion)
class FacebookSignIn
enum Error: Swift.Error
case unableToInitializeGraphRequest
case unexpectedGraphResponse
case permissionsIsNotGranted
case unexpectedLoginResponse
case canceled
struct Permissions
static let email = "email"
static let profile = "public_profile"
static func isValidPermissions(_ permissions: Set<AnyHashable>) -> Bool
return permissions.contains(email) && permissions.contains(profile)
static var permissions: [String]
return [email, profile]
public static let shared = FacebookSignIn()
private init()
extension FacebookSignIn
func signIn(from: UIViewController, completion: Result<SignInResponse>.Completion?)
let manager = FBSDKLoginManager()
manager.loginBehavior = .native
if !isValidToken
manager.logOut()
if let token = FBSDKAccessToken.current()
let interval = token.expirationDate.timeIntervalSince(Date())
if interval > 300 // At least 5 min token will be valid
performLogin
switch $0
case .failure(let error):
completion?(.failure(error))
case .success(let info):
completion?(.success(SignInResponse(accessToken: token.tokenString, userInfo: info)))
else
FBSDKAccessToken.refreshCurrentAccessToken [weak self] _, _, error in
if let error = error
manager.logOut()
completion?(.failure(error))
else
let token = FBSDKAccessToken.current()?.tokenString ?? "" // Should be always valid value at this point.
self?.performLogin
switch $0
case .failure(let error):
completion?(.failure(error))
case .success(let info):
completion?(.success(SignInResponse(accessToken: token, userInfo: info)))
else
manager.logIn(withReadPermissions: Permissions.permissions, from: from) [weak self] result, error in
if let error = error
manager.logOut()
completion?(.failure(error))
return
guard let result = result else
manager.logOut()
completion?(.failure(Error.unexpectedLoginResponse))
return
let permissions = result.grantedPermissions ?? Set<AnyHashable>()
let token = result.token?.tokenString ?? "" // Should be always valid value at this point.
if result.isCancelled
manager.logOut()
completion?(.failure(Error.canceled))
else if Permissions.isValidPermissions(permissions)
self?.performLogin
switch $0
case .failure(let error):
completion?(.failure(error))
case .success(let info):
completion?(.success(SignInResponse(accessToken: token, userInfo: info)))
else
manager.logOut()
completion?(.failure(Error.permissionsIsNotGranted))
private var isValidToken: Bool
guard let token = FBSDKAccessToken.current() else
return false
return Permissions.isValidPermissions(token.permissions ?? Set<AnyHashable>())
private func makeGraphRequest() -> FBSDKGraphRequest?
guard FBSDKAccessToken.current().tokenString != nil else
return nil
// You might not get email: https://developers.facebook.com/docs/facebook-login/permissions/v2.4
// Note, even if you request the email permission it is not guaranteed you will get an email address. For example,
// if someone signed up for Facebook with a phone number instead of an email address, the email field may be empty.
let fields = "email,id,first_name,last_name,gender"
return FBSDKGraphRequest(graphPath: "me", parameters: ["fields": fields])
private func performLogin(completion: Result<[String: String]>.Completion?)
let manager = FBSDKLoginManager()
guard let request = makeGraphRequest() else
manager.logOut()
completion?(.failure(Error.unableToInitializeGraphRequest))
return
_ = request.start _, result, error in
if let e = error
manager.logOut()
completion?(.failure(e))
else if let result = result as? [String: String]
completion?(.success((result)))
else
manager.logOut()
completion?(.failure(Error.unexpectedGraphResponse))
public struct SignInResponse
public let accessToken: String
public let userInfo: [String: String]
public init(accessToken: String, userInfo: [String: String])
self.accessToken = accessToken
self.userInfo = userInfo
public enum Result<T>
case success(T)
case failure(Swift.Error)
public typealias Completion = (Result<T>) -> Void
【讨论】:
【参考方案5】:如果你想使用原生按钮试试这个:
let buttonText = NSAttributedString(string: "your text here")
facebookButton.setAttributedTitle(buttonText, for: .normal)
【讨论】:
【参考方案6】:截至 2017 年 6 月,已为 Swift 3 和最新版本的 FBSDK 更新了可接受的答案,代码如下所示-
@IBAction func fbLoginPressed(_ sender: Any)
let fbLoginManager: FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logIn(withReadPermissions: ["email"], from: self) (result, error) in
if error == nil
if let fbLoginResult = result
if fbLoginResult.grantedPermissions != nil && fbLoginResult.grantedPermissions.contains("email")
self.getFBUserdata()
func getFBUserdata()
if FBSDKAccessToken.current() != nil
FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"id,name,first_name, last_name, picture.type(large), email"]).start(completionHandler: (cnnection, result, error) in
if error == nil
print(result ?? "Error in getFBUserdata function")
)
【讨论】:
以上是关于FacebookSDK(4.1.x) 自定义登录 UI 按钮 - Swift(1.2)的主要内容,如果未能解决你的问题,请参考以下文章