Gunja Patel
Gunja Patel

Reputation: 289

Facebook login using Social and Accounts Frameworks in iOS swift

I am trying to fb login using Social and Accounts Frameworks.

Facebook login via social framework in ios
Follow this question and convert code into swift but getting error

The operation couldn’t be completed. (com.apple.accounts error 6.)

Find many question on stack overflow in objective c but not in swift.

My Code:

import Social
import Accounts

class ViewController: UIViewController {

    var facebookAccount : ACAccount!       
    let appIdKey : NSString = "*************"
    var facebookAccount : ACAccount!
    var isFacebookAvailable = Int()
    var globalMailId = NSString()
    var fbName = NSString()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.accountStore = ACAccountStore()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @IBAction func fbLogin(sender: UIButton) {

        let accountType = self.accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook)

        var dictFB = [String : AnyObject]()
        dictFB[ACFacebookAppIdKey] = "*************"
        dictFB[ACFacebookPermissionsKey] = ["publish_profile","email","user_friends"]
        dictFB[ACFacebookAudienceKey] = ACFacebookAudienceFriends

        self.accountStore.requestAccessToAccountsWithType(accountType, options: dictFB) { (granted : Bool, error : NSError?) -> Void in
            if granted {
                let accounts : NSArray = self.accountStore.accountsWithAccountType(accountType)
                self.facebookAccount = accounts.lastObject as! ACAccount

                let facebookCredentials = self.facebookAccount.credentials

            } else {
                print("Error getting permission : \(error!.localizedDescription)")
                self.isFacebookAvailable = 0
            }
        }
    }
}

EDIT 1: I have updated my code like this

@IBAction func fbLogin(sender: UIButton) {

   if SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook) {

       let accountType = self.accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook)

        var dictFB = [String : AnyObject]()
        dictFB[ACFacebookAppIdKey] = "463272290501295"
        dictFB[ACFacebookPermissionsKey] = ["publish_profile","email","user_friends"]
        dictFB[ACFacebookAudienceKey] = ACFacebookAudienceFriends

        self.accountStore.requestAccessToAccountsWithType(accountType, options: dictFB) { (granted : Bool, error : NSError?) -> Void in
             if error != nil {
                 print("Error getting permission : \(error)")
              } else {
                  print("granted : \(granted)") //print false here
                  if granted {
                     let accounts : NSArray = self.accountStore.accountsWithAccountType(accountType)
                     self.facebookAccount = accounts.lastObject as! ACAccount

                     let facebookCredentials = self.facebookAccount.credentials
                    } else {
                        dispatch_async(dispatch_get_main_queue(), { () -> Void in
                            self.showAlert(nil, message: "Permission not granted For Your Application")
                        })
                    }
                }
            }
        } else {
            self.askForSettingsChange("Please login to a Facebook", message: "Go to settings to login Facebook")
        }
    }
    func showAlert(title : String? , message : String?) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
        let action = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
        alert.addAction(action)

        self.presentViewController(alert, animated: true, completion: nil)
    }
    func askForSettingsChange(title : String? , message : String?) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
        let settingAction = UIAlertAction(title: "Settings", style: .Default) { (action : UIAlertAction) -> Void in
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!) // go to settings
            })
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: nil)

        alertController.addAction(settingAction)
        alertController.addAction(cancelAction)
        self.presentViewController(alertController, animated: true, completion: nil)
    }

check into phone settings if facebook user present or not, if present then go to further but it will not grant permission.

Upvotes: 4

Views: 2590

Answers (4)

serhanaksut
serhanaksut

Reputation: 648

Here is my example view controller to test Facebook login. Sure that your Facebook app settings are correct.

import UIKit
import Accounts
import Social

class ViewController: UIViewController {

// MARK: - Properties
var facebookAccount: ACAccount?

// MARK: - Lifecycle
override func viewDidLoad() {
    super.viewDidLoad()
}

// MARK: - Actions
@IBAction func buttonFBLoginAction() {
    facebookLogin { [unowned self] credential in
        guard let _ = credential else { return }
        // TODO: - Send token to service for login process.
        self.performSegueWithIdentifier("ShowSecondVC", sender: nil)
    }
}

// MARK: - Custom Methods
private func facebookLogin(completion: (credential: ACAccountCredential?) -> Void) {
    let store = ACAccountStore()
    let facebook = store.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook)
    let apiKey = "**************"
    let readPermissions = ["public_profile", "email"]
    let loginParameters: [NSObject: AnyObject] = [ACFacebookAppIdKey: apiKey, ACFacebookPermissionsKey: readPermissions]
    store.requestAccessToAccountsWithType(facebook, options: loginParameters) { granted, error in
        if granted {
            let accounts = store.accountsWithAccountType(facebook)
            self.facebookAccount = accounts.last as? ACAccount

            let credentials = self.facebookAccount?.credential
            completion(credential: credentials)
        } else {
            if let error = error {
                print(error.localizedDescription)
            }
            completion(credential: nil)
        }
    }
}
}

Upvotes: 0

An Chin
An Chin

Reputation: 463

I think I might know what your problem is... Honestly, AcAccountStore is not the best way to use Facebook...

Here you go, the options you gave in your "ACFacebookPermissionsKey" is wrong. It should be "public_profile", not "publish"....

Good luck.

Upvotes: 0

Reema
Reema

Reputation: 1230

Facebook Login using Accounts Framework (Swift)

var facebookAccount: ACAccount?

        let options: [NSObject : AnyObject] = [ACFacebookAppIdKey: "YOUR_FACEBOOK_API_KEY", ACFacebookPermissionsKey: ["publish_stream","publish_actions"],ACFacebookAudienceKey:ACFacebookAudienceFriends]
        let accountStore = ACAccountStore()
        let facebookAccountType = accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook)

            accountStore.requestAccessToAccountsWithType(facebookAccountType, options: options) { (granted, error) -> Void in
                if granted
                {
                    let accounts = accountStore.accountsWithAccountType(facebookAccountType)
                    self.facebookAccount = accounts.last as? ACAccount
                    let accountsArray=accountStore.accountsWithAccountType(facebookAccountType) as NSArray

                    self.facebookAccount=accountsArray.lastObject as? ACAccount
                    var dict:NSDictionary
                    dict=NSDictionary()

                    dict=self.facebookAccount!.dictionaryWithValuesForKeys(["properties"])
                    let properties:NSDictionary=dict["properties"] as! NSDictionary
                    print("facebook Response is-->:%@",properties)
                }
                else
                {
                    if error.code == Int(ACErrorAccountNotFound.rawValue) {
                        dispatch_async(dispatch_get_main_queue(), { () -> Void in
                            self.displayAlert("There is no Facebook accounts configured. you can add or created a Facebook account in your settings.")
                        })
                    } else {
                        dispatch_async(dispatch_get_main_queue(), { () -> Void in
                            self.displayAlert("Permission not granted For Your Application")
                        })
                    }

                }
            }

Upvotes: 1

mustafa
mustafa

Reputation: 15464

Here is a helper class that I used in my app

import Accounts
import Social

class LoginManager: NSObject {

    var facebookAccount: ACAccount?

    func facebookLogin(completion: (credential: ACAccountCredential?) -> Void) {
        let store = ACAccountStore()
        let facebook = store.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierFacebook)
        let apiKey = "YOUR_FACEBOOK_API_KEY"
        let loginParameters: [NSObject: AnyObject] = [ACFacebookAppIdKey: apiKey, ACFacebookPermissionsKey: []]
        store.requestAccessToAccountsWithType(facebook, options: loginParameters) { granted, error in
            if granted {
                let accounts = store.accountsWithAccountType(facebook)
                self.facebookAccount = accounts.last as? ACAccount

                let credentials = self.facebookAccount?.credential
                completion(credential: credentials)
            } else {
                completion(credential: nil)
            }
        }
    }
}

Upvotes: 2

Related Questions