iosfacebookswiftsocial-frameworkaccounts-framework

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.


Solution

  • 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)
                }
            }
        }
    }