Facebook FBSDK for iOS allows a developer to add login/sign-up buttons quickly without any hassle. Let’s learn how we can install the SDK using Cocoapods and use it in Swift 3. As of now SDK’s documentation is only in Objective-C and converting that to Swift can be a challenging task for the new developers. The goal behind this tutorial is to translate the documented functions into equivalent Swift 2 or 3 code and give the developers a head start on the FBSDK.
Steps for using FBSDK for login:
We will be using Cocoapods to install the FBSDK, but before that, you should be a Facebook developer and also have a target app listed under your name or the company. Check this link for more information.
Step 1: Create a new Single View application using Xcode, and add one Podfile to it either by creating an empty document with the name ‘Podfile’ (notice, there’s no file extension to it.) or through the terminal using the following command:
$cd /PathToYourProject/ProjectName
$pod init
Note: If you are not familiar with Cocoapods, then I would suggest you to go through this guide for better understanding.
The commands mentioned above will create an empty Podfile, which you can edit using either the Xcode or code editor tools such as Sublime. Now, open the file, and add the following lines:
pod 'FBSDKCoreKit'
pod 'FBSDKLoginKit'
pod 'FBSDKShareKit'
Go back to the Terminal in the same directory and type pod install or pod install –verbose for debugging and hit the return key. Once done, open your project using the newly created YourProject.xcworkspace file and you will be good to go.
The advantage over traditional drag and drop is that the Cocoapods makes it very easy to maintain, remove, or upgrade the frameworks. Also, you will have full access to the source code to modify the SDK easily.
Step 2: This step is about importing the SDK and start using the services offered. To do so, open the AppDelegate.swift file and add import FBSDKCoreKit line in the beginning. The use of import statement in Swift allows you to have mentioned Objective-C or C libraries added directly into your program.
Step 3: The next step requires calling necessary functions in our AppDelegate file so that FBSDK can properly initialize and interact during the callbacks. To do so, in the didFinishLaunchingWithOptions method, call FBSDK function as shown below in the code:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
return true
}
Next, in the applicationDidBecomeActive method, add FBSDKAppEvents.activateApp() anywhere in the function, and then in the openURL url:Options: method, add the following code:
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
let sourceApplication: String? = options[UIApplicationOpenURLOptionsSourceApplicationKey] as? String
return FBSDKApplicationDelegate.sharedInstance().application(app, openURL: url, sourceApplication: sourceApplication, annotation: nil)
}
If we look at the FBSDK documents for the same, the write-up asks a developer to add these lines in deprecated functions, which is not only a bad idea but also interferes with other functionalities in the application that requires URL callbacks. For example, if you have implemented OAuth sign-in, then during the callbacks, the app might not open for further actions.
Step 4: In this step, we will be editing our info.plist file to add information about the FB application for which login button has been created. Right click or double tap on the Info.plist file, and click on Open As > Source Code. Just before the </dict> tag at the bottom, add the code from this link. Please be sure to edit it as per your Facebook app ID and name.
Step 4: Lets now edit our ViewController.swift file to add a FB login button on the screen. In the viewDidLoad() function, add the following code:
func viewDidLoad() {
super.viewDidLoad()
let loginView: FBSDKLoginButton = FBSDKLoginButton()
loginView.delegate = self
loginView.center = self.view.center
self.view.addSubview(loginView)
}
Also, conform your class with FBSDKLoginButtonDelegate in order to call the delegate functions in your class.
Right now, the button is in the center, but you can alter it’s position by changing the frame and then adding it to the view. For example, check the code below, which place a bigger version of the FB login button a few pixels away from the center. Of course, you can have layout constraints in place of it or an UIButton on storyboard inherting FB login button properties. Just in case, here’s an example:
func loginButtonDesign() {
/** Calculating the position: First we take the current device's height, divide it by 4, and substract it from the total height For placing the button in the center we substract login button frame from the center co-ordinates To Change the position vertically, but keep it in the center, change the var verticalPosition which is currently set to the CGFloat value 4*/
let verticalPosition: CGFloat = 4.0
let positionOfFrame = self.view.center.y - self.view.center.y / verticalPosition
let positionX = self.view.center.x - (loginView.frame.width + 60) / 2
let positionY = self.view.center.y - (loginView.frame.height + 15) / 2
let finalPositionY = positionY + positionOfFrame
//Frame of the Login Button
let widthOfFBButton = loginView.frame.width + 60
let heightOfFBButton = loginView.frame.height + 15
//Placing the button on the frame
loginView.frame = CGRectMake(positionX, finalPositionY, widthOfFBButton, heightOfFBButton)
self.view.addSubview(loginView)
}
That’s it, run your application and you will see the login button appearing on the screen. But, it won’t work just yet as we are not making the Graph API call to fetch the user data as per the permissions we have requested for. To do so, follow along the next step.
Step 5: First of all let’s declare the permissions we require from the user signing in the app. You can create a private data member of type array of strings and assign it to the loginView FBSDK Button we just created. For example, we can have permissions as such:
let permissionsToRead = ["public_profile", "email", "user_birthday", "user_hometown","user_location","user_friends", "user_work_history","user_education_history", "user_photos","user_relationships"]
And in the viewDidLoad(), assign the same using loginView.readPermissions = permissionsToRead
Step 6: This step is composed of two main actions required by the application to access data of the user. First is a delegate function from the SDK telling us if the login button completed with a result, and second is for making a Graph API call for fetching the user data.
Let’s create another private data member of type Dictionary containing fields we need to access from the API. As for the example, it goes as follows:
et graphRequestParameters = ["fields": "name, birthday, first_name, last_name, gender, location, hometown, relationship_status, email, work, education, photos"]
Note: This data member only has one key, and the values for it are a set of values, do not confuse it with different keys.
Now let’s create a function which will be accepting this as a parameter and make a call:
//Mark: GraphRequestForFetchingUserData
func graphRequestToReturnUserData(graphParameters: Dictionary<String, String>) {
let graphRequest: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: graphParameters)
graphRequest.startWithCompletionHandler({
(connection, result, error) -> Void in
if ((error) != nil) {
NSLog("Error For Facebook: \(error.localizedDescription)") //Error Handling
} else {
print(result) //or assign it to a variable using facebookData = result as! Dictionary
}
})
}
Please note that this is happening in the same class, but you can put it in separate classes to differentiate the functionality. Next, let’s call that delegate function to get the data.
In the FBSDK, we have loginButton:didCompleteWithResult result:, you can implement it this way:
//MARK: Log In request
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if (error != nil) {
NSLog("Error in Facebook Login \(error.localizedDescription)")
} else if result.isCancelled {
NSLog("User Canceled The Login")
} else {
if result.grantedPermissions.contains("email") {
print(result.grantedPermissions)
NSLog("Got email access")
graphRequestToReturnUserData(graphRequestParameters)
}
}
}
In the above function, we have a set of cases which includes: First, if the login failed, second if the user canceled the login and third where we got permissions to access the user data with a list of permissions provided. Notice, only when we get the permissions, we are making a call to the Graph API for accessing the information as doing it before the successful login will result in error due the absence of access token. Once everything goes as mentioned, you will be able to see the user data printing in your console. You can further take this for performing operations such as creating a new user on the server or checking if the record is already there in the database.
Not only this, but FBSDK can also be used to share posts, Messenger API calls and what not.
Bonus:
FBSDK not only allows a user to log in, but also retains the access token in the app so that you can check whether the user is already logged in or not. You can call the method FBSDKAccessToken.currentAccessToken() to check whether the token is nil or not.If it’s nil, ask the user to log in, if not, you can directly perform the required operations. In other cases, if you want the user to log out of the application, directly call FBSDKLoginManager().logOut() anywhere in your app from the view or a UIButton. Don’t forget to import the SDK in your program.
For any questions, drop a comment.
What does this mean:
Also, conform your class with FBSDKLoginButtonDelegate in order to call the delegate functions in your class.
Conforming to a protocol means that you must implement functions in class from the conforming protocol.
Here, in this case, you must implement functions from FBSDKLoginButtonDelegate in your class.
There are mistakes in the code …
(connection, result, error) ->
the ->: si surely the > sign. greater-than
Hi, that’s because of the encoding. I will try to fix this.
Thank you!
Happy Coding 🙂
Where in the code is this. This is very unclear.
and then in the openURL url:Options: method, add the following code: