graphRequest.start returns no data - ios

I'm using the Facebook SDK for login with iOS using Swift 3.
This my code. The problem is that no values are returned.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var email: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var uLoginButton: UIButton!
let loginButton: FBSDKLoginButton = {
let button = FBSDKLoginButton()
button.readPermissions = ["email"]
return button;
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(loginButton);
loginButton.center = view.center
loginButton.delegate = self
if (FBSDKAccessToken.current() != nil) {
fetchProfile();
}
self.style()
}
func fetchProfile(){
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields" : "email, name, first_name, last_name, picture.type(large)"])
let connection = FBSDKGraphRequestConnection()
connection.add(graphRequest, completionHandler: { (connection, result, error) in
if error != nil {
//do something with error
print("No Data returned")
print(result)
} else {
//do something with result
print("Data returned")
print(result)
}
})
connection.start()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func style(){
self.email.layer.cornerRadius = 15;
self.password.layer.cornerRadius = 15;
self.uLoginButton.layer.cornerRadius = 15;
}
}
extension ViewController : FBSDKLoginButtonDelegate{
internal func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
// when the login is correct!
print("Success login!");
fetchProfile()
}
internal func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
FBSDKAppEvents.activateApp()
}
internal func loginButtonWillLogin(_ loginButton: FBSDKLoginButton!) -> Bool {
return true
}
}

In Swift 3, this is how you want to perform Graph Request.
Initialize FBSDKGraphRequest
Initialize FBSDKGraphRequestConnection
Add request to request connection
Start connection.
so,
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields" : "email"])
let connection = FBSDKGraphRequestConnection()
connection.add(graphRequest, completionHandler: { (connection, result, error) in
if error != nil {
//do something with error
} else {
//do something with result
}
})
connection.start()

Related

Facebook SDK with iOS swift not open in UIWebView [duplicate]

This question already has answers here:
How to integrate Facebook without redirect Safari browser in iOS app with latest FBSDK
(6 answers)
Closed 6 years ago.
I am using Xcode 8.2.1 and FBSDK 4.19.0
I want to open login in with Facebook in a web view instead of Safari.
This is my ViewController:
`import UIKit
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
#IBOutlet var loginButton: FBSDKLoginButton!
var result:NSDictionary=[:]
override func viewDidLoad() {
super.viewDidLoad()
loginButton.delegate = self
if (FBSDKAccessToken.current()) != nil{
fetchProfile()
}
}
func fetchProfile(){
let parameters = ["fields": "name, gender, email, picture.type(large)"]
FBSDKGraphRequest(graphPath: "me", parameters: parameters).start(completionHandler: { (connection, result, error) -> Void in
if(error == nil)
{
self.result = result as! NSDictionary
print(self.result)
}
else
{
print("error \(error)")
}
})
}
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
print("completed login")
}
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
}
func loginButtonWillLogin(_ loginButton: FBSDKLoginButton!) -> Bool {
return true
}
}
`
Set the loginBehaviour to .web for FBSDKLoginManager object.
let loginManager = FBSDKLoginManager()
loginManager.loginBehaviour = .web
Since you are using FBSDKLoginButton, in viewDidLoad method, write
loginButton.loginBehaviour = .web

Changing ViewController if user is Facebook Logged in

I'm having quite some troubles implementing Facebook login in my iOS , everything works fine if the user is not already logged in, the application fetches correctly the data from Facebook and pass them to the next ViewController , instead if is already logged in it should automatically segue to a recap page that shows user's info but i can't make it happen, currently I'm using this method :
override func viewDidLoad() {
super.viewDidLoad()
LoginButton.delegate = self
if (FBSDKAccessToken.currentAccessToken() != nil) {
self.performSegueWithIdentifier("Login", sender: self)
}
}
but in the console i get :
Facebook_Login.LoginViewController: 0x7fc04a519ca0 on Facebook_Login.ViewController: 0x7fc04a41c1e0 whose view is not in the window hierarchy!
i've also tried using the viewdidAppear method, but it segues to the recap page without updating the variables so i get an empty page
here' the complete code:
View Controller 1
import UIKit
import FBSDKLoginKit
class ViewController: UIViewController,FBSDKLoginButtonDelegate {
var nome1:String = ""
var cognome1:String = ""
var email1:String = ""
var compleanno:String = ""
var città:String = ""
var genere:String = ""
var immagine_url:String = ""
#IBOutlet weak var LoginButton: FBSDKLoginButton!
#IBAction func LoginAction(sender: AnyObject) {
LoginButton.delegate = self
LoginButton.readPermissions = ["email"]
}
func FetchInfo(){
print("scarico le informazioni...")
let parametri = ["fields":"email, first_name, last_name, birthday, hometown, gender, picture.type(large)"]
FBSDKGraphRequest(graphPath: "me", parameters: parametri).startWithCompletionHandler{(connection,result,error) -> Void in
if (error != nil){
print ("errore")
return
}
else {
if let email = result["email"] as? String {
print(email)
self.email1 = email
}
if let nome = result["first_name"] as? String {
print(nome)
self.nome1 = nome
}
if let cognome = result["last_name"] as? String {
print(cognome)
self.cognome1 = cognome
}
if let compleanno = result["birthday"] as? String{
print(compleanno)
}
if let città = result["hometown"] as? String{
print(città)
}
if var genere = result["gender"] as? String{
if (genere == "male"){
genere = "maschio"
}
else {
genere = "femmina"
}
print(genere)
}
}
if let picture = result["picture"] as? NSDictionary, data = picture["data"] as? NSDictionary, url = data["url"] as? String{
self.immagine_url = url
print(self.immagine_url)
}
}
return
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!){
if (result.isCancelled == true){
print("cancellato")
}
else {
print("login effettuato")
FetchInfo()
self.performSegueWithIdentifier("Login", sender: self)
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!){
}
func loginButtonWillLogin(loginButton: FBSDKLoginButton!) -> Bool{
return true
}
#IBAction func returned(segue:UIStoryboardSegue){
}
override func viewDidLoad() {
super.viewDidLoad()
LoginButton.delegate = self
}
override func viewDidAppear(animated: Bool) {
if (FBSDKAccessToken.currentAccessToken() != nil) {
FetchInfo()
if(nome1 == ""){
}
else {
self.performSegueWithIdentifier("Login", sender: self)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destinazione:LoginViewController = segue.destinationViewController
as! LoginViewController
destinazione.temp_nome = nome1
destinazione.temp_cognome = cognome1
destinazione.temp_email = email1
destinazione.img_profile_url = immagine_url
}
}
ViewController 2:
import UIKit
import FBSDKLoginKit
class LoginViewController: UIViewController, FBSDKLoginButtonDelegate {
var temp_nome = ""
var temp_cognome = ""
var temp_email = ""
var img_profile_url:String = ""
#IBOutlet weak var Nome_Utente: UILabel!
#IBOutlet weak var email: UILabel!
#IBOutlet weak var Immagine_Utente: UIImageView!
#IBOutlet weak var Login_button: FBSDKLoginButton!
#IBAction func Login_button_Action(sender: AnyObject) {
Login_button.delegate = self
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!){
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!){
self.performSegueWithIdentifier("Back", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
Nome_Utente.text = "\(temp_nome)" + " " + "\(temp_cognome)"
email.text = "\(temp_email)"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
First of all, avoid to reset your LoginButton.delegate in the LoginAction() function.
If the user is already logged in, to avoid an useless call to the Facebook Graph API (if you do not necessarily need to update his informations), you can store your user informations in CoreData or in a NSUserDefault.
If you never used it you can use the CDHelper lib (CoreDataHelper) which will allow you to use it without difficulties.
Hope I was helpful, if not, do not hesitate to give us a feedback.
Btw, in your viewDidAppear(animated: Bool) function, you have to call super.viewDidAppear(animated) !

Facebook Login for Swift with facebook iOS SDK 4.9.1

I got trouble with facebook iOS SDK 4.9.1 on integrating facebook login using swift. and main trouble is unable to find any guideline regarding it for swift.
http://www.brianjcoleman.com/tutorial-how-to-use-login-in-facebook-sdk-4-0-for-swift/
http://swiftdeveloperblog.com/facebook-sdk-ios-login-example-with-swift/
IOS Swift and Facebook SDK
I try to implement below but it doesn't work at all.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if (FBSDKAccessToken.currentAccessToken() != nil)
{
// User is already logged in, do work such as go to next view controller.
}
else
{
let loginView : FBSDKLoginButton = FBSDKLoginButton()
self.view.addSubview(loginView)
loginView.center = self.view.center
loginView.readPermissions = ["public_profile", "email", "user_friends"]
loginView.delegate = self
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This is for viewcontroller :
import FBSDKLoginKit
class ViewController: UIViewController,FBSDKLoginButtonDelegate {
#IBOutlet weak var fbLoginView: FBSDKLoginButton!
override func viewDidLoad() {
super.viewDidLoad()
if(FBSDKAccessToken.currentAccessToken() == nil){
print("Not Logged ")
}
else{
print("Logged In")
}
fbLoginView.readPermissions = ["public_profile","email","user_birthday"]
fbLoginView.delegate = self
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!)
{
if error == nil
{
print("login complete")
let request = FBSDKGraphRequest(graphPath:"me", parameters:["fields":"name,gender,birthday,first_name,last_name,email"])
request.startWithCompletionHandler
{
(connection, result, error) in
if error != nil
{
print ("error \(error)")
}
else if let userData = result as? NSDictionary
{
var frstname = userData["first_name"] as? String
var lastname = userData["last_name"] as? String
var gender = userData["gender"] as? String
var birthday = userData["birthday"] as? String
var email = userData["email"] as? String
print(result)
}
}
}
else
{
print(error.localizedDescription)
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!)
{
print("user logged out")
}
}
In App Delegate override the following method as :
func application(application: UIApplication,openURL url: NSURL, sourceApplication: String?,annotation: AnyObject) -> Bool
{
return FBSDKApplicationDelegate.sharedInstance().application(application,openURL: url,sourceApplication: sourceApplication,annotation: annotation)
}
Swift 5+
In App Delegate override the following method as :
func application(application: UIApplication,openURL url: NSURL, sourceApplication: String?,annotation: AnyObject) -> Bool
{
return ApplicationDelegate.sharedInstance().application(application,openURL: url,sourceApplication: sourceApplication,annotation: annotation)
}

Doesn't call Facebook loginButton didCompleteWithResult

I followed the tutorial here to integrate Facebook login on my application. I can login successfully with that button, but it doesn't call my method didCompleteWithResult upon login to fetch user details. This is my code.
import UIKit
class LoginViewController: UIViewController, FBSDKLoginButtonDelegate {
#IBOutlet weak var loginBtn: FBSDKLoginButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func configureFacebook()
{
loginBtn.readPermissions = ["public_profile", "email", "user_friends"];
loginBtn.delegate = self
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!){
FBSDKGraphRequest.init(graphPath: "me", parameters: ["fields":"first_name, last_name, picture.type(large)"]).startWithCompletionHandler { (connection, result, error) -> Void in
let strFirstName: String = (result.objectForKey("first_name") as? String)!
let strLastName: String = (result.objectForKey("last_name") as? String)!
let strPictureURL: String = (result.objectForKey("picture")?.objectForKey("data")?.objectForKey("url") as? String)!
print("Welcome, \(strFirstName) \(strLastName)")
//self.profilePic.image = UIImage(data: NSData(contentsOfURL: NSURL(string: strPictureURL)!)!)
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!)
{
}
}
Option-1
I dont know where you add this method in here I submit answer in dynamically , customize your self..
override func viewDidLoad() {
super.viewDidLoad()
configureFacebook() // if you want here add here or else if you want to load the facebook details in Button action add there
// Do any additional setup after loading the view.
}
func configureFacebook()
{
loginBtn.readPermissions = ["public_profile", "email", "user_friends"];
loginBtn.delegate = self
}
option-2
if you add the delegate in directly in your viewcontroller do like for example

Swift how to close Facebook graph block

I want, and I don't know how to =(, close my Facebook graph block
My problem is that I want to save the username of my user facebook in a variable to use it later (another view controller), but I can't because my block is closed after I try to save the data.
This is my delegate function :
// Facebook Delegate Methods
func loginButton(connection: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if (error != nil)
{
println("Error")
}
else {
println("User logged in")
self.returnUserData()
}
}
And this is my function which use facebook graph api
// Here my block that I want to close, maybe with completion closure inside
func returnUserData()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"])
// Launch asynchronous function
var userName : String = "error"
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
println("Error: \(error)")
}
else
{
println(result)
userName = result["first_name"] as! String
}
})
}
Can somebody help me ?
Take a look at this example, you can set the variable outside of the scope of your closure then ask it to perform a specific func when it's value is set like so:
import UIKit
class ViewController: UIViewController {
var myString : String = "123" {
didSet {
self.stringUpdated()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
myString = "456" // this would take place in your graph request closure
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func stringUpdated() {
println("got it, string is \(myString)")
}
}

Resources