Showing posts with label Social. Show all posts
Showing posts with label Social. Show all posts

Thursday, April 28, 2016

Facebook SDK and Swift - Create a custom login button programmatically

The FBSDKLoginButton style is like this:


To create a custom Facebook login button, follow these two tutorials first:

Facebook SDK and Swift - Create a Facebook Login Button
Facebook SDK and Swift - Display User Name and Profile Picture

Then remove the FBSDKLoginButton and create a UIButton instead. Add this to viewDidLoad()with Xcode 7.3 (Swift 2.2):


let btnSize : CGFloat = 100
let btnLogin = UIButton(frame: CGRectMake(0,0,btnSize,btnSize))
btnLogin.center = CGPoint(x: view.center.x, y: 400)
btnLogin.setImage(UIImage(named: "facebook_logo.png"), forState: UIControlState.Normal)
btnLogin.addTarget(self, action: #selector(btnLoginPressed), forControlEvents: UIControlEvents.TouchUpInside)
        
//Circular button
btnLogin.layer.cornerRadius = btnSize/2
btnLogin.layer.masksToBounds = true
btnLogin.layer.borderColor = UIColor.blackColor().CGColor
btnLogin.layer.borderWidth = 2

view.addSubview(btnLogin)

and then add this:

func btnLoginPressed() {

let loginManager = FBSDKLoginManager()
loginManager.logInWithReadPermissions(["public_profile"], fromViewController: self, handler: { (response:FBSDKLoginManagerLoginResult!, error: NSError!) in
    if(error == nil){
        print("No Error")
        self.getFacebookUserInfo()
        }
    })
}

Result:


Related Information:

Google Sign-In for iOS - Create a custom sign-in button programmatically

Google Sign-In for iOS - Create a custom sign-in button programmatically

The GIDSignInButton can be assigned as one of the following styles (See GIDSignInButton Class):

GIDSignInButtonStyle.Standard => 230x48


GIDSignInButtonStyle.Wide     => 312x48


GIDSignInButtonStyle.IconOnly =>  48x48

However, we may need custom styles other than the above sign-in buttons. For example the 48x48 IconOnly style is a bit small on the screen and hence we want to enlarge it. So the code below shows how to implement a custom Google sign-in button with these properties:


  • Custom image
  • Custom button size
  • Circular shape

To get started, implement a standard Google Sign-In button with instructions in this tutorial:

Google Sign-In for iOS - Create a GIDSignInButton programmatically in Swift

Then remove the GIDSignInButton and add a UIButton instead:


    var btnSignIn : UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        ...
        
        let btnSize : CGFloat = 100
        btnSignIn = UIButton(frame: CGRectMake(0,0,btnSize,btnSize))
        btnSignIn.center = view.center
        btnSignIn.setImage(UIImage(named: "google_logo.png"), forState: UIControlState.Normal)
        btnSignIn.addTarget(self, action: #selector(btnSignInPressed), forControlEvents: UIControlEvents.TouchUpInside)

        //Circular button
        btnSignIn.layer.cornerRadius = btnSize/2
        btnSignIn.layer.masksToBounds = true
        btnSignIn.layer.borderColor = UIColor.blackColor().CGColor
        btnSignIn.layer.borderWidth = 2
        view.addSubview(btnSignIn)

        ...
    }
    
    func btnSignInPressed() {
        GIDSignIn.sharedInstance().signIn()
    }

Result:


Related Information:

Facebook SDK and Swift - Create a custom login button programmatically

Wednesday, April 27, 2016

Google Sign-In for iOS - Get User Name, Email and Profile Picture without Nofitication

Previously, I have worked out how to implement a Google Sign-In button and display the user email and profile picture in these posts:

Google Sign-In for iOS - Create a GIDSignInButton programmatically in Swift
Google Sign-In for iOS - Display User Email and Profile Picture

When the user is just signed in with the two examples above, AppDelegate.swift posts a notification including the user information and then ViewController.swift receives the user information in the receiveToggleAuthUINotification function.

However, I need to separate the sign-in button and the display of the user information in two different view controllers. The view controller to show the user information is displayed AFTER signed in and hence the notification is unable to be detected. The solution is to include the code below:

if (GIDSignIn.sharedInstance().hasAuthInKeychain()) {
    print("signed in")
    print(GIDSignIn.sharedInstance().currentUser.profile.email)
    print(GIDSignIn.sharedInstance().currentUser.profile.name)
    print(GIDSignIn.sharedInstance().currentUser.profile.imageURLWithDimension(100))
}

Related Information:

Google Sign-In for iOS - Create a GIDSignInButton programmatically in Swift
Google Sign-In for iOS - Display User Email and Profile Picture

Wednesday, March 16, 2016

Google Sign-In for iOS - Display User Email and Profile Picture

Update April 27, 2016:
Step 3 - ViewController.swift is modified with Xcode 7.3 (Swift 2.2).

This post shows how to display the user email and profile picture with Google Sign-In for iOS.

Procedure

1. Create a basic sign-in button with instructions in this tutorial:

Google Sign-In for iOS - Create a GIDSignInButton programmatically in Swift

2. Modify AppDelegate.swift:

//Modify signIn function with didSignInForUser:

    func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!,
        withError error: NSError!) {
            if (error == nil) {

                let name = user.profile.name
                let email = user.profile.email
                var imageURL = ""
                if user.profile.hasImage {
                    imageURL = user.profile.imageURLWithDimension(100).absoluteString
                }
                NSNotificationCenter.defaultCenter().postNotificationName(
                    "ToggleAuthUINotification",
                    object: nil,
                    userInfo: ["statusText": "Signed in user:\n\(name)""email" : email, "imageURL" : imageURL])

            }
...

//Modify signIn function with didDisconnectWithUser:

    func signIn(signIn: GIDSignIn!, didDisconnectWithUser user:GIDGoogleUser!,
        withError error: NSError!) {
            NSNotificationCenter.defaultCenter().postNotificationName(
                "ToggleAuthUINotification",
                object: nil,
                userInfo: ["statusText": "User has disconnected.", "email" : ""])

    }

3. Modify ViewController.swift:


Update April 27, 2016:

import UIKit

class ViewController: UIViewController, GIDSignInUIDelegate {

    var btnSignIn : GIDSignInButton!
    var btnSignOut : UIButton!
    var btnDisconnect : UIButton!
    var label : UILabel!
    
    var imageView : UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        GIDSignIn.sharedInstance().uiDelegate = self
        
        btnSignIn = GIDSignInButton(frame: CGRectMake(0,0,230,48))
        btnSignIn.center = view.center
        btnSignIn.style = GIDSignInButtonStyle.Standard
        view.addSubview(btnSignIn)
        
        btnSignOut = UIButton(frame: CGRectMake(0,0,100,30))
        btnSignOut.center = CGPointMake(view.center.x, 100)
        btnSignOut.setTitle("Sign Out", forState: UIControlState.Normal)
        btnSignOut.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
        btnSignOut.setTitleColor(UIColor.cyanColor(), forState: UIControlState.Highlighted)
        btnSignOut.addTarget(self, action: #selector(btnSignOutPressed), forControlEvents: UIControlEvents.TouchUpInside)
        view.addSubview(btnSignOut)
        
        btnDisconnect = UIButton(frame: CGRectMake(0,0,100,30))
        btnDisconnect.center = CGPointMake(view.center.x, 200)
        btnDisconnect.setTitle("Disconnect", forState: UIControlState.Normal)
        btnDisconnect.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
        btnDisconnect.setTitleColor(UIColor.cyanColor(), forState: UIControlState.Highlighted)
        btnDisconnect.addTarget(self, action: #selector(btnDisconnectPressed), forControlEvents: UIControlEvents.TouchUpInside)
        view.addSubview(btnDisconnect)
        
        label = UILabel(frame: CGRectMake(0,0,300,200))
        label.center = CGPointMake(view.center.x, 430)
        label.numberOfLines = 0
        label.text = "Please Sign in."
        label.textAlignment = NSTextAlignment.Center
        view.addSubview(label)
        
        imageView = UIImageView(frame: CGRectMake(0, 0, 100, 100))
        imageView.center = view.center
        view.addSubview(imageView)
        
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: #selector(receiveToggleAuthUINotification(_:)),
            name: "ToggleAuthUINotification",
            object: nil)
        
        toggleAuthUI()
    }
    
    func btnSignOutPressed() {
        print(GIDSignIn.sharedInstance().currentUser.profile.email)
        print(GIDSignIn.sharedInstance().currentUser.profile.name)
        
        GIDSignIn.sharedInstance().disconnect()
        label.text = "Disconnecting."
    }
    
    func btnDisconnectPressed() {
        label.text = "Signed out."
        toggleAuthUI()
    }
    
    func toggleAuthUI() {
        print("toggleAuthUI")
        if (GIDSignIn.sharedInstance().hasAuthInKeychain()){

            // Signed in
            btnSignIn.hidden = true
            btnSignOut.hidden = false
            btnDisconnect.hidden = false
            
            //NEW!! The code below is required if the app is restarted and already signed in previously.
            if (GIDSignIn.sharedInstance().currentUser == nil) {
                print("no user info")
                GIDSignIn.sharedInstance().signInSilently()
            }
        } else {
            btnSignIn.hidden = false
            btnSignOut.hidden = true
            btnDisconnect.hidden = true
        }
    }
    
    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self,
            name: "ToggleAuthUINotification",
            object: nil)
    }
    
    @objc func receiveToggleAuthUINotification(notification: NSNotification) {
        if (notification.name == "ToggleAuthUINotification") {
            self.toggleAuthUI()
            if notification.userInfo != nil {
                let userInfo:Dictionary<String,String!> =
                notification.userInfo as! Dictionary<String,String!>
                self.label.text = userInfo["statusText"]!+"\n\(userInfo["email"]!)"
                if userInfo["imageURL"] == nil {
                    self.imageView.image = nil
                } else {
                    let url = NSURL(string: userInfo["imageURL"]!)!
                    self.imageView.image = UIImage(data: NSData(contentsOfURL: url)!)
                }
            }
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

=====
Original post March 16, 2016:

//Modified blue texts:


    var imageView : UIImageView!
    
    override func viewDidLoad() {

        ...

        label = UILabel(frame: CGRectMake(0,0,300,200))
        label.center = CGPointMake(view.center.x, 430)
        label.numberOfLines = 0
        label.text = "Please Sign in."
        label.textAlignment = NSTextAlignment.Center
        view.addSubview(label)
        
        imageView = UIImageView(frame: CGRectMake(0, 0, 100, 100))
        imageView.center = view.center
        view.addSubview(imageView)

        ...

//And modify this:


    @objc func receiveToggleAuthUINotification(notification: NSNotification) {
        if (notification.name == "ToggleAuthUINotification") {
            self.toggleAuthUI()
            if notification.userInfo != nil {
                let userInfo:Dictionary<String,String!> =
                notification.userInfo as! Dictionary<String,String!>
                self.label.text = userInfo["statusText"]!+"\n\(userInfo["email"]!)"
                if userInfo["imageURL"] == nil {
                    self.imageView.image = nil
                } else {
                    let url = NSURL(string: userInfo["imageURL"]!)!
                    self.imageView.image = UIImage(data: NSData(contentsOfURL: url)!)
                }
            }
        }

    }
=====

Result

Related Information:

Google Sign-In for iOS - Create a GIDSignInButton programmatically in Swift
Google Sign-In for iOS - Get User Name, Email and Profile Picture without Nofitication
Google Sign-In for iOS - Create a custom sign-in button programmatically
Facebook SDK and Swift - Display User Name and Profile Picture

Tuesday, March 15, 2016

Google Sign-In for iOS - Create a GIDSignInButton programmatically in Swift

Update: 

May 27, 2016 - Update Step 4 for CocoaPods 1.0.

This tutorial explains how to create a Google Sign-In button without storyboard using Google Sign-In for iOS. The code below was developed in Swift 2 with Xcode 7.2.1.

More information: Google Sign-In iOS SDK Release Notes

Procedure

1. Install CocoaPods. (More information about CocoaPods is written at the bottom of this post.)

Type this command in the terminal:

sudo gem install cocoapods

2. Create an Xcode project and close it.

3. Go to the project directory in the terminal and type:

pod init

4. In the Podfile just created, edit it as below:

pod 'Google/SignIn'

(You may open the Podfile with this command: open -a Xcode Podfile)

Update May 27, 2016:

The above code may not work with the new CocoaPods 1.0. If you see error like this:


The dependency `GoogleMaps` is not used in any concrete target.

Try modify your Podfile as below:

target "Project_name" do
    pod 'Google/SignIn'


end

5. Run the terminal and type the command below in the project directory:

pod install

You may see something like this in the terminal:



5. Open the projectName.xcworkspace file just automatically created. (Don't open the original .xcodeproj file)




You may see the project navigator like this with a new Pods folder:



6. We are going to download a configuration file. Just follow the instructions in the Google Sign-In for iOS page.

Click the GET A CONFIGURATION FILE Button.



Enter the App name and iOS Bundle ID. Click CONTINUE TO Choose and configure services.



Click ENABLE GOOGLE SIGN-IN.




Click CONTINUE TO Generate configuration files.




Download the GoogleService-Info.plist file and drag it to the Xcode project.




Click Continue Adding Sign-In. The browser will be redirected to Integrating Google Sign-In into your iOS app.



Select Swift.
Don't select Download the dependencies and configure your Xcode project.




7. Open the GoogleService-Info.plist  file in the Xcode project. Copy the value of REVERSED_CLIENT_ID.


Select the projectName as Targets. Select Info -> URL Types -> + sign.




Paste the value you just copied into URL Schemes. Give the Identifier any name you like, such as REVERSED_CLIENT_ID.

Select the + sign again and paste the bundle identifier in URL Schemes.




8. Add a temporary Objective-C file to your project. You may give it any name you like.



Select Create Bridging Header to configure an Objective-C bridging header.


Delete the temporary Objective-C file you just created.

8. In the projectName-Bridging-Header.h file just created, add this line:


#import <Google/SignIn.h>


9. Replace the AppDelegate.swift file with this file from GitHub. Put comment characters with these lines to remove warnings: 


//let userId = user.userID                  // For client-side use only!
//let idToken = user.authentication.idToken // Safe to send to the server
let name = user.profile.name

//let email = user.profile.email

10. Edit ViewController.swift as below:

import UIKit

class ViewController: UIViewController, GIDSignInUIDelegate {
    
    var btnSignIn : GIDSignInButton!
    var btnSignOut : UIButton!
    var btnDisconnect : UIButton!
    var label : UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        GIDSignIn.sharedInstance().uiDelegate = self
        
        btnSignIn = GIDSignInButton(frame: CGRectMake(0,0,230,48))
        btnSignIn.center = view.center
        btnSignIn.style = GIDSignInButtonStyle.Standard
        view.addSubview(btnSignIn)
        
        btnSignOut = UIButton(frame: CGRectMake(0,0,100,30))
        btnSignOut.center = CGPointMake(view.center.x, 100)
        btnSignOut.setTitle("Sign Out", forState: UIControlState.Normal)
        btnSignOut.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
        btnSignOut.setTitleColor(UIColor.cyanColor(), forState: UIControlState.Highlighted)
        btnSignOut.addTarget(self, action: "btnSignOutPressed:", forControlEvents: UIControlEvents.TouchUpInside)
        view.addSubview(btnSignOut)
        
        btnDisconnect = UIButton(frame: CGRectMake(0,0,100,30))
        btnDisconnect.center = CGPointMake(view.center.x, 200)
        btnDisconnect.setTitle("Disconnect", forState: UIControlState.Normal)
        btnDisconnect.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
        btnDisconnect.setTitleColor(UIColor.cyanColor(), forState: UIControlState.Highlighted)
        btnDisconnect.addTarget(self, action: "btnDisconnectPressed:", forControlEvents: UIControlEvents.TouchUpInside)
        view.addSubview(btnDisconnect)
        
        
        label = UILabel(frame: CGRectMake(0,0,200,100))
        label.center = CGPointMake(view.center.x, 400)
        label.numberOfLines = 0 //Multi-lines
        label.text = "Please Sign in."
        label.textAlignment = NSTextAlignment.Center
        view.addSubview(label)
        
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: "receiveToggleAuthUINotification:",
            name: "ToggleAuthUINotification",
            object: nil)
        
        toggleAuthUI()
    }
    
    func btnSignOutPressed(sender: UIButton) {
        GIDSignIn.sharedInstance().disconnect()
        label.text = "Disconnecting."
    }
    
    func btnDisconnectPressed(sender: UIButton) {
        label.text = "Signed out."
        toggleAuthUI()
    }
    
    func toggleAuthUI() {
        if (GIDSignIn.sharedInstance().hasAuthInKeychain()){
            // Signed in
            btnSignIn.hidden = true
            btnSignOut.hidden = false
            btnDisconnect.hidden = false
        } else {
            btnSignIn.hidden = false
            btnSignOut.hidden = true
            btnDisconnect.hidden = true
        }
    }
    
    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self,
            name: "ToggleAuthUINotification",
            object: nil)
    }
    
    @objc func receiveToggleAuthUINotification(notification: NSNotification) {
        if (notification.name == "ToggleAuthUINotification") {
            self.toggleAuthUI()
            if notification.userInfo != nil {
                let userInfo:Dictionary<String,String!> =
                notification.userInfo as! Dictionary<String,String!>
                self.label.text = userInfo["statusText"]
            }
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

The above code is derived from Google's ViewController.swift example.

Various Sign-In Button Sizes (See GIDSignInButton Class):

GIDSignInButtonStyle.Standard => 230x48
GIDSignInButtonStyle.Wide     => 312x48
GIDSignInButtonStyle.IconOnly =>  48x48

11. If you build the code now, you'll see this error:

clang: error: linker command failed with exit code 1 (use -v to see invocation)



Try to disable the bitcode:

Targets -> Build Settings -> Build Options -> Enable Bitcode (Search: bitcode) -> No


12. Build and run the code. It should work.

Result


Press the Sign in button.

Enter the ID (Gmail address) and password.



Press Allow.

The username is displayed.



=============

Additional Information

Some CocoaPods commands for reference:

1. Check the CocoaPods version installed:
pod --version

2. Check if CocoaPods framework of a project is outdated:

Go to the directory including the Podfile. Type:

pod outdated



The pod outdated command also checks if new CocoaPods version is available.

3. Update CocoaPods using the install command:

sudo gem install cocoapods

4. Update CocoaPods to a pre-release version:

sudo gem install cocoapods --pre

5. Update local repositories:

pod update