From FBSDKGraphRequest to Storyboard - ios

i'm total beginner in coding, but i have a big question :)
I dont know how to get information to display on Main Storyboard form FBSDKGraphRequest.
What i should do next to get picture to Storyboard? I hope someone can help me :)
Using Swift 3, Xcode 8
Facebook login is working and code is:
func getFBUserData(){
if((FBSDKAccessToken.current()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil){
self.dict = result as? [String : AnyObject]
print(result!)
print(self.dict)
}
})
}

I see it as four steps -- my apologies to you if you already know some of this.
Drag an UIImageView from the object library in interface builder to a view in your storyboard.
Connect the UIImageView to your code as an IBOutlet and name it. Do this by control dragging from your new UIImageView to your code, and then in the popup specify an outlet and name the UIImageView. In my case I named it 'facebookPicture'
Get the URL for the image from the FaceBook result. The following sample code drills down into the result dictionary step by step. There are many ways to shorten this.
#IBOutlet var facebookPicture: UIImageView!
func getFBUserID(){
if((FBSDKAccessToken.current()) != nil) {
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).start(
completionHandler: {
[weak self] (connection, result, error) -> Void in
guard let strongSelf = self else { return }
if let error = error {
print("Failed to download FB user with error:. \(error)")
}
if (error == nil) {
let resultDictSwift = result as! Dictionary<String, Any>
if let picture = resultDictSwift["picture"] as? Dictionary<String, Any> {
if let pictureData = picture["data"] as? Dictionary<String, Any> {
if let pictureURL = NSURL(string: (pictureData["url"] as? String)! ) {
strongSelf.downloadImage(url: pictureURL as URL)
}
}
}
print(result!)
let FBID = resultDictSwift["id"]
strongSelf.facebookID = FBID as! String?
print("User FB id: \(strongSelf.facebookID!)")
}
})
}
}
Download the image from the URL location. The following does this asynchronously and uses a previous stack overflow answer here When the download is complete, it sets the result of the download to be the image in your UIImageView
func getDataFromUrl(url: URL, completion: #escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url) { data, response, error in
completion(data, response, error)
}.resume()
}
func downloadImage(url: URL) {
print("Download Started")
getDataFromUrl(url: url) { data, response, error in
guard let data = data, error == nil else { return }
print(response?.suggestedFilename ?? url.lastPathComponent)
print("Download Finished")
DispatchQueue.main.async() {
self.facebookPicture.image = UIImage(data: data)
}
}
}
I hope this helps!

In Swift 3
#IBAction func btnFacebookTapped(_ sender: UIButton)
{
let loginManager = FBSDKLoginManager()
loginManager.logIn(withReadPermissions: ["user_about_me", "email" , "user_birthday","user_hometown"], from: self) { (loginResult, error) in
if error != nil
{
self.showalert(strMessage: (error?.localizedDescription)!)
}
else
{
if loginResult?.grantedPermissions == nil
{
self.showalert(strMessage: "Login Permissions not granted")
return
}
if (loginResult?.grantedPermissions.contains("email"))!
{
self.getFBUserData()
}
}
}
}
func getFBUserData()
{
FBSDKGraphRequest.init(graphPath: "me?fields=id,name,email,first_name,last_name,cover,picture.type(large),gender,birthday,hometown", parameters: nil).start(completionHandler: { (connection , result , error ) in
if(error == nil){
DispatchQueue.main.async {
let dictionary = result as! NSDictionary
print(dictionary)
print("Name : \(dictionary.value(forKey: "name")!)")
print("FB ID : \(dictionary.value(forKey: "id")!)")
}
}else{
self.showalert(strMessage: "Somthig Went Wrong..!")
}
})
}

Related

Cannot fetch Facebook uploaded images

func fetchListOfUserPhotos() {
// let graphRequest = GraphRequest(graphPath: "me", parameters: ["fields": "picture"])
graphRequest.start(completionHandler: { [self] (_, result, error) in
if error != nil {
print(error as Any)
} else {
print(result)
}
})
}
getting empty data.. please help me to resolve this issue.

Facebook Login not working in IOS SDK

I am struggling with the issue of Facebook login, Yesterday Facebook login working correctly but today when I run my app it's not working don't know why, why it's not working suddenly I already configured all things related to Facebook login in Facebook develop console everything is configured
Please help me out if you have any idea, I already enable Keychain sharing also.
Code for Facebook Login
#IBAction func onClickFacebookLoginAction(_ sender: Any) {
var message = String()
if Reachability.isConnectedToNetwork() == true{
let loginView:FBSDKLoginManager = FBSDKLoginManager()
loginView.loginBehavior = FBSDKLoginBehavior.web
loginView.logIn(withReadPermissions: ["email","public_profile","user_friends"], from: self, handler: { (result, error) in
if(error != nil){
print("Error while try to login with facebook-\(error?.localizedDescription)")
}else if (result?.isCancelled)!{
print("User cancel the facebook login")
}else{
if result?.grantedPermissions != nil{
if (result?.grantedPermissions .contains("email"))!{
self.ShowProgressHUD()
self.fetchUserInfo()
}else{
message = message.appending("Facebook email permission error")
self.showAlertMessage(message: message, title: "")
}
}
}
})
}
}
func fetchUserInfo() -> Void {
if (FBSDKAccessToken.current() != nil) {
let graphRequest:FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "/me", parameters:["fields": "id, first_name, last_name, name, email, picture"])
graphRequest.start(completionHandler: { (connection, result, error) in
if(error != nil){
self.showAlertMessage(message: (error?.localizedDescription)!, title: "")
}
else
{
print("Result is:\(result)")
self.dictionary = result as! [String : AnyObject]
let name = self.dictionary["name"] as!String
let email = self.dictionary["email"] as! String
let token = FBSDKAccessToken.current().tokenString
print("name is -\(name)")
print("email is -\(email)")
print("token is -\(token)")
DispatchQueue.main.async {
let SelectionViewObj = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.navigationController?.pushViewController(SelectionViewObj, animated: true)
}
}
})
}
}
This is the code i am using to authenticate facebook.its working like a charm.Just check or replace with this.
self.fbLoginManager = FBSDKLoginManager.init()
fbLoginManager.loginBehavior = FBSDKLoginBehavior.web
self.fbLoginManager.logIn(withReadPermissions: ["email"], from: self) { (result, error) -> Void in
if (error == nil) {
let fbloginresult : FBSDKLoginManagerLoginResult = result!
if fbloginresult.grantedPermissions != nil && fbloginresult.grantedPermissions.contains("email") {
if((FBSDKAccessToken.current()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"id, first_name, last_name, email, gender, birthday, location"]).start(completionHandler: { (connection, result, error) -> Void in
if error != nil {
print(error?.localizedDescription ?? "error in facebook login...!")
return
}
if let dict = result as? NSDictionary {
print("facebook login result --->\n\(dict)")
guard let id = dict["id"] else {
print("Ooops... id = nil")
return
}
// let firstName: String = dict["first_name"] as? String ?? ""
// let lastName : String = dict["last_name"] as? String ?? ""
// let email : String = dict["email"] as? String ?? ""
self.fbLoginManager.logOut()
}
})
}
} else {
print("facebook ---> login canceled")
}
} else {
print(error?.localizedDescription ?? "facebook login has error")
}
}
This is how I used to log in with Facebook,
#IBAction func act_loginFB(_ sender: UIButton) {
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logIn(withReadPermissions: ["public_profile", "email",], from: self) { (result, error) -> Void in
if (error == nil){
let fbloginresult : FBSDKLoginManagerLoginResult = result!
if(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: { (connection, result, error) -> Void in
if (error == nil){
//everything works print the user data
print(result)
let data: [String:AnyObject] = (result as? [String : AnyObject])!
print(data)
let email: String = data["email"]! as! String
print(email)
}
})
}
}
Check you added the correct FacebookAppID and FacebookDisplayName in the info.plist

Facebook iOS SDK and Swift: how to get user's hometown?

I am working with iOS 9.2 & Swift 2.1 & FBSDKVersion: 4.7.0.
I tried with Graph API Explorer, at that time I am getting the desired output.
The converted code is in Objective-C and I changed it to Swift.
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "/me", parameters: ["fields": "hometown"], HTTPMethod: "GET")
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil){
print("Error: \(error)")
}
else{
print("fetched details: \(result)")
})
See below example and add hometown option into "fields" parameter of FBSDKGraphRequest object and also change:
func fetchUserProfile()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"id, email, name, picture.width(480).height(480)"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
print("Error took place: \(error)")
}
else
{
print("Print entire fetched result: \(result)")
let id : NSString = result.valueForKey("id") as! String
print("User ID is: \(id)")
if let userName = result.valueForKey("name") as? String
{
self.userFullName.text = userName
}
if let profilePictureObj = result.valueForKey("picture") as? NSDictionary
{
let data = profilePictureObj.valueForKey("data") as! NSDictionary
let pictureUrlString = data.valueForKey("url") as! String
let pictureUrl = NSURL(string: pictureUrlString)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let imageData = NSData(contentsOfURL: pictureUrl!)
dispatch_async(dispatch_get_main_queue()) {
if let imageData = imageData
{
let userProfileImage = UIImage(data: imageData)
self.userProfileImage.image = userProfileImage
self.userProfileImage.contentMode = UIViewContentMode.ScaleAspectFit
}
}
}
}
}
})
}
Also refer to this link
Fetching user details from Facebook in iOS

Can't return output of closure using graph api

If I call this method to obtain a Facebook profile picture it does not work, response gets printed with the data but when I return it its nil, can anyone help?
func getProfilePicture() -> NSData?{
var response:NSData?
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"picture.type(large)"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if error != nil {
print("login error: \(error!.localizedDescription)")
return
}
let json = JSON(result)
let profilePicture = json["picture"]["data"]["url"].stringValue
if let url = NSURL(string: profilePicture) {
if let pictureData = NSData(contentsOfURL: url){
response = pictureData
}
}
})
print(response)
return response
}
The Facebook call is using an async completionblock and your return statement will return nil before the call is done loading. That is why you also should use a completion block in your method.
Here is an example how to do this:
func getProfilePicture(completion: (pictureData: NSData?, error: NSError?) -> Void) {
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"picture.type(large)"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
var pictureData: NSData?
let json = JSON(result)
let profilePicture = json["picture"]["data"]["url"].stringValue
if let url = NSURL(string: profilePicture) {
pictureData = NSData(contentsOfURL: url)
}
completion(pictureData: pictureData, error: error)
})
}
You can call this code like this:
self.getProfilePicture {(pictureData, error) -> Void in
if error != nil {
print("login error: \(error!.localizedDescription)")
}
print(pictureData)
}

FacebookSDK(4.1.x) Custom Login UI Button - Swift(1.2)

Following this tutorial, I have managed to make a Facebook Login Button working. However, it is assigning the button image automatically from the SDK and it is not customisable (as it is not getting created on Storyboard), so I am unable to use my own button image or text instead.
I believe this part of the code (in ViewDidLoad) is assigning the button:
let loginView : FBSDKLoginButton = FBSDKLoginButton()
self.view.addSubview(loginView)
loginView.center = self.view.center
loginView.readPermissions = ["public_profile", "email"]
loginView.delegate = self
What I need to do is creating a #IBOutlet Button on Storyboard and customise it from there. How can I do that?
Login with custom button and access token.
Get user info in facebook sdk 4.x
Swift
#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)
}
})
}
}
Updated answer using the last Facebook SDK (01/05/2016) and Swift 2.1
Create a UIButton with Interface Builder or by code and link the action of that button with this:
#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()
}
}
}
}
The happy case of the previous code triggers the function self.getFBUserData() so you have to implement that function in the same file
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)
}
})
}
}
I did it successfully in 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)
}
})
}
}
Reusable class (Swift 4).
Usage: 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
}
If you want to use the native button try this out:
let buttonText = NSAttributedString(string: "your text here")
facebookButton.setAttributedTitle(buttonText, for: .normal)
As of June 2017, the accepted answer updated for Swift 3 and latest version of FBSDK, the code looks like below-
#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")
}
})
}
}

Resources