# Facebook Login for iOS - Advanced
#### - [Login Review](#review)
#### - [Custom Login Button](#custom-login-button)
#### - [Using the Interface Builder](#interface-builder)
#### - [Access Tokens](#access-tokens)
#### - [Profiles](#profiles)
#### - [Track Profile Pictures](#profile_picture_view)
#### - [Setting the Authorization Type](#auth_type)
## Login Review {#review}
If your app asks for more than `public_profile` and `email`, Facebook must review it before you release it. Learn more about the review process and what's required to pass review.
[Login Review Guide](https://developers.facebook.com/docs/facebook-login/review)
## Custom Login Button {#custom-login-button}
Instead of using the Facebook-branded login button (explained in [Facebook Login for iOS - Quickstart](https://developers.facebook.com/documentation/facebook-login/ios#6--add-facebook-login-to-your-code)) you may want to design a custom layout and behavior. In the following code example we invoke the login dialog using the login manager class (`LoginManager`) and a custom button (`UIButton`). You can use any other custom user interface or event handling to invoke the login dialog.
```
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Add a custom login button to your app
let loginButton = UIButton(type: .custom)
loginButton.backgroundColor = .darkGray
loginButton.frame = CGRect(x: 0, y: 0, width: 180, height: 40)
loginButton.center = view.center
loginButton.setTitle("My Login Button", for: .normal)
// Handle clicks on the button
loginButton.addTarget(self, action: #selector(loginButtonClicked), for: .touchUpInside)
view.addSubview(loginButton)
}
// Once the button is clicked, show the login dialog
func loginButtonClicked() {
let loginManager = LoginManager()
loginManager.logIn(permissions: ["public_profile"], from: self) { result, error in
if let error = error {
print("Encountered Erorr: \(error)")
} else if let result = result, result.isCancelled {
print("Cancelled")
} else {
print("Logged In")
}
}
}
}
```
## Using the Interface Builder {#interface-builder}
These steps are required for version 12.0.0 and later of the Facebook iOS SDK. Apps using the `Interface Builder` may crash if you have not completed this step.
To add the login button graphically in `Interface Builder`:
1. Add a `UIButton` object to your layout. Set constraints to position it.
2. In `Identity inspector` change the `Class` property to `FBSDKLoginButton`.
Now your layout looks like this:
**Note**: Do not set a module for the `FBSDKLoginButton` class. It should show **None**:
**Note**: You may see the following error in Xcode logs due to a known issue with XCFrameworks:
```
[Storyboard] Unknown class FBSDKLoginButton in Interface Builder file.
```
You can fix this by "pre-loading" the FBSDKLoginButton class before the storyboard loads by adding the following to your `application:didFinishLaunchingWithOptions:` method:
```
// For Swift
_ = FBLoginButton.self
// For Objective-C
[FBSDKLoginButton class];
```
## Access Tokens {#access-tokens}
### Notifications {#access-tokens-notifications}
You can track `AccessToken.current` changes with the `.AccessTokenDidChange` notification in `NotificationCenter`. This allows you to respond to changes in the user's login state:
```
NotificationCenter.default.addObserver(
forName: .AccessTokenDidChange,
object: nil,
queue: .main
) { notification in
if notification.userInfo?[AccessTokenDidChangeUserIDKey] != nil {
// Handle user change
}
}
```
The iOS SDK can update `AccessToken.current` over time, such as when the SDK refreshes a token with a longer expiration date. Therefore, you should check the `userInfo` dictionary in the notification for `AccessTokenDidChangeUserIDKey` to determine if the user has changed.
## Profiles {#profiles}
`Profile` contains public profile information, allowing you to personalize your app with the user's name and profile picture. You can load the logged in user's profile using `loadCurrentProfile(completion:)`.
```
Profile.loadCurrentProfile { profile, error in
if let firstName = profile?.firstName {
print("Hello, \(firstName)")
}
}
```
You can set the `enableUpdatesOnAccessTokenChange` property to `true` to have the profile automatically loaded to `Profile.current`. This also lets you to observe the `.ProfileDidChange` notification to respond to profile changes:
```
Profile.enableUpdatesOnAccessTokenChange(true)
NotificationCenter.default.addObserver(
forName: .ProfileDidChange,
object: nil,
queue: .main
) { notification in
if let currentProfile = Profile.current {
// Update for new user profile
}
}
```
## Showing Profile Pictures {#profile_picture_view}
The `FBProfilePictureView` class provides an easy way to display someone's Facebook profile picture. Simply set the `profileID` property on the instance. You can set it to a value of `AccessToken.current.userID` to show the profile picture of the person currently logged in.
```
let profilePictureView = FBProfilePictureView()
profilePictureView.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
profilePictureView.profileID = AccessToken.current!.userID
view.addSubview(profilePictureView)
```
## Setting the Authorization Type {#auth_type}
The default `auth_type` for Facebook Login buttons in the Facebook SDK for iOS is [rerequest](https://developers.facebook.com/documentation/facebook-login/guides/permissions/request-revoke#handling). If you want to avoid requesting permissions that were previously denied, set `auth_type` to `nil`. You can also set it to [reauthorize](https://developers.facebook.com/documentation/facebook-login/auth-vs-data#data-access-expiration) to show the data reauthorization dialog if the user's data access has expired.
The following example shows how to set the `auth_type` in Swift.
```
let loginButton = FBLoginButton()
// Set to nil for no auth_type
button.authType = nil
// Or set to reauthorize
button.authType = .reauthorize
```
The following example shows how to set the `auth_type` using a login configuration with a login manager.
```
let config = LoginConfiguration(
permissions: [],
tracking: .enabled,
messengerPageId: nil,
authType: nil
)
let loginManager = LoginManager()
loginManager.logIn(viewController: self, configuration: config!) { loginResult in
// Do something with loginResult
}
```