At WWDC 2019, Apple introduced Sign in with Apple. It provides a simple and secure way for people to sign in to apps using the Apple IDs they already have. In order to support Sign in with Apple, developers must use the sign in button provided by Apple — ASAuthorizationAppleIDButton
.
Unfortunately, the ASAuthorizationAppleIDButton
class does not have storyboard support. Therefore, developers will have to add the sign in button programmatically, causing them not able to enjoy the benefits of using storyboards.
The benefits of using storyboards include:
- Can easily setup auto layout constraints.
- Better visualisation on the overall screen design.
- Much easier to handle various size classes.
- Less code written means less bugs.
In this article, I will show you how you can use ASAuthorizationAppleIDButton
in storyboard by using a custom UIButton
.
Generally, here’s what you need to do.
- Create a custom
UIButton
. - Add
ASAuthorizationAppleIDButton
as subview. - Create
IBInspectable
for button corner radius. - Create
IBInspectable
for button type and style. - Handle button tap event.
With all that being said, let’s go through the steps in detail one by one.
#1. Create a Custom UIButton
To create a custom UIButton
, press ⌘N → select Cocoa Touch Class. We will name the custom button MyAuthorizationAppleIDButton
and make it subclass of UIButton
.
Next, implement all the required init
methods so that the custom button can be used in storyboard.
class MyAuthorizationAppleIDButton: UIButton {
override public init(frame: CGRect) {
super.init(frame: frame)
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
#2. Add ASAuthorizationAppleIDButton as Subview
Before we proceed with the implementation, let’s configure our Xcode in a way that can ease us in the custom button development.
Getting Ready
First, let’s open your storyboard and MyAuthorizationAppleIDButton.swift
side by side using the assistant canvas. To do this, press ⌘⇧O (command + shift + O), type your storyboard name and then press ⌥↩︎ (option + enter) to open it at the assistant canvas.
You can learn more about Xcode navigation shortcuts in this article.
Next, in your storyboard, add a UIButton
to the view controller and set its class to MyAuthorizationAppleIDButton
.
In addition, add the following auto layout constraints to the button.
- Horizontally in container
- Vertically in container
- Width: 250pt
- Height: 46pt
Lastly, go to the Editor menu, and then enable Automatically Refresh Views. By enabling this, you will be able to see the button’s appearance being rendered simultaneously whenever there are changes in MyAuthorizationAppleIDButton
class. You should see this in action in a short while.
Adding ASAuthorizationAppleIDButton
Now, let’s head back to MyAuthorizationAppleIDButton.swift
and continue the custom button implementation.
In order to use ASAuthorizationAppleIDButton
, we must first import the AuthenticationServices
framework.
import AuthenticationServices
We also need to define a private ASAuthorizationAppleIDButton
instance named authorizationButton
.
private var authorizationButton: ASAuthorizationAppleIDButton!
Do note that authorizationButton
is of implicitly unwrapped optional type because we are confident that it won’t be nil
for the entire lifecycle of the custom button.
To learn more about implicitly unwrapped optional, check out this article.
Next, we will need to make our custom button look exactly the same as the ASAuthorizationAppleIDButton
. The idea is to add the ASAuthorizationAppleIDButton
as subview and force it to follow the size of our custom button.
We can achieve that by overriding the draw(_:)
method of our custom button.
override public func draw(_ rect: CGRect) {
super.draw(rect)
// Create ASAuthorizationAppleIDButton
authorizationButton = ASAuthorizationAppleIDButton(authorizationButtonType: .default, authorizationButtonStyle: .black)
// Show authorizationButton
addSubview(authorizationButton)
// Use auto layout to make authorizationButton follow the MyAuthorizationAppleIDButton's dimension
authorizationButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
authorizationButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 0.0),
authorizationButton.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0.0),
authorizationButton.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0.0),
authorizationButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0.0),
])
}
Up until this point, you will find that the button you added to storyboard just now is still a boring white colour system button.
To trigger the rendering in storyboard, add the @IBDesignable
keyword before the start of the MyAuthorizationAppleIDButton
class’s definition and see the system button magically transform into the Sign in with Apple button.
@IBDesignable
class MyAuthorizationAppleIDButton: UIButton {
// ...
// ...
// ...
}
After successfully showing the Sign in with Apple button in storyboard, we can now work on customising the button’s appearance.
By looking into the Apple official documentation, you will find that there are 3 styling properties in ASAuthorizationAppleIDButton
that we can utilise to change the appearance of the button.
In the next section, we will look into how to add these 3 properties into our custom button. On top of that, we will also make all these 3 properties available for customisation in storyboard attributes inspector by using @IBInspectable
.
#3. Create IBInspectable for Button Corner Radius
The way to make corner radius available in the storyboard attributes inspector is quite straightforward. We just need to define a cornerRadius
variable for MyAuthorizationAppleIDButton
and tag it with @IBInspectable
.
@IBInspectable
var cornerRadius: CGFloat = 6.0
Note that we are using 6.0 as the default value of cornerRadius
as that is the default corner radius of ASAuthorizationAppleIDButton
.
Next, go to the draw(_:)
method and set cornerRadius
as authorizationButton
‘s corner radius.
authorizationButton.cornerRadius = cornerRadius
Here’s the updated MyAuthorizationAppleIDButton.swift
.
We can now head over to storyboard and try changing the corner radius value in the attributes inspector.
You should be able to see the custom button’s appearance in storyboard being updated when you update the corner radius value in the attributes inspector.
#4. Create IBInspectable for Button Type and Style
IBInspectable
only supports basic data types such as String
, Int
and CGFloat
. In other words, data types such as ASAuthorizationAppleIDButton.ButtonType
and ASAuthorizationAppleIDButton.Style
are not supported by IBInspectable
. Therefore, we must find a way to keep track of the button type and style by using basic data type.
Fortunately, by looking into the definition of both ASAuthorizationAppleIDButton.ButtonType
and ASAuthorizationAppleIDButton.Style
, you will notice that both of them have raw value of type Int
.
As a result, we can define variables of type Int
and use @IBInspectable
to make them available in the storyboard attributes inspector.
@IBInspectable
var authButtonType: Int = ASAuthorizationAppleIDButton.ButtonType.default.rawValue
@IBInspectable
var authButtonStyle: Int = ASAuthorizationAppleIDButton.Style.black.rawValue
As you can see, for code above, authButtonType
will take the ASAuthorizationAppleIDButton.ButtonType.default
‘s raw value as its default value. Meanwhile, authButtonStyle
will take ASAuthorizationAppleIDButton.Style.black
‘s raw value as its default value.
Next, we will update the draw(_:)
method to initialise the ASAuthorizationAppleIDButton
instance using authButtonType
and authButtonStyle
.
let type = ASAuthorizationAppleIDButton.ButtonType.init(rawValue: authButtonType) ?? .default
let style = ASAuthorizationAppleIDButton.Style.init(rawValue: authButtonStyle) ?? .black
authorizationButton = ASAuthorizationAppleIDButton(authorizationButtonType: type,
authorizationButtonStyle: style)
Notice that we need to handle the initialisation failure for both type and style by falling back to their default value, this is because we have no control over the value being inputted from the storyboard attributes inspector.
With all that being done, we can head back to storyboard and see everything in action!
Pretty cool isn’t it! 😎
At this point, if you create an IBAction
and connect it to our custom button touch up inside event, you will notice that the action is not being triggered. This is because the touch up inside event has been hijacked by the ASAuthorizationAppleIDButton
subview.
In the following section, we will look into how we can solve this issue.
#5. Handle Button Tap Event
The solution to the button tap event issue is pretty simple, the idea is to handle the authorizationButton
‘s touch up inside event and forward it to our custom button.
Let’s go ahead and set the selector for the authorizationButton
‘s touch up inside event.
// Set selector for touch up inside event so that can forward the event to MyAuthorizationAppleIDButton
authorizationButton.addTarget(self, action: #selector(authorizationAppleIDButtonTapped(_:)), for: .touchUpInside)
Here’s the implementation of the authorizationAppleIDButtonTapped(_:)
method.
@objc func authorizationAppleIDButtonTapped(_ sender: Any) {
// Forward the touch up inside event to MyAuthorizationAppleIDButton
sendActions(for: .touchUpInside)
}
Note that the sendActions(for:)
method will trigger the touch up inside event of our custom button.
Here’s the updated MyAuthorizationAppleIDButton.swift
.
With that, the MyAuthorizationAppleIDButton
should be able to trigger its touch up inside event without any problem.
Something to Take Note
While testing the sample code, I noticed that there are auto layout constraint warnings being shown at the debug area when the custom button has width larger than 375pt or height larger than 64pt.
It seems like Apple has added auto layout constraints to limit the dimension of the ASAuthorizationAppleIDButton
. I would recommend all developers to go through the Human Interface Guidelines, and only use the suggested button dimension in order to avoid apps being rejected by Apple.
Wrapping Up
The custom button that we have created is fully functioning and highly customisable. You can definitely reuse it in your other iOS projects. Feel free to get the full sample code here.
To reuse it, just add MyAuthorizationAppleIDButton.swift
to your iOS project, after that add a custom button of type MyAuthorizationAppleIDButton
to your storyboard, then you are good to go.
Last but not least, if you do not want Xcode to rebuild your projects every time you make changes on your code, feel free to disable Automatically Refresh Views under the Editor menu.
Further Readings
- Integrate ‘Sign in with Apple’ with Firebase Authentication
- Sign in With Apple implementation tutorial
- IBInspectable / IBDesignable
- Sign in with Apple button human interface guidelines
If you find this article helpful, feel free to share it. If you have any comments or questions, please leave it in the comment section below.
Follow me on Twitter for more articles related to iOS development.
Thanks for reading! 👨🏼💻
👋🏻 Hey!
While you’re still here, why not check out some of my favorite Mac tools on Setapp? They will definitely help improve your day-to-day productivity. Additionally, doing so will also help support my work.
- ✨ Bartender: Superpower your menu bar and take full control over your menu bar items.
- ✨ CleanShot X: The best screen capture app I’ve ever used.
- ✨ PixelSnap: Measure on-screen elements with ease and precision.
- ✨ iStat Menus: Track CPU, GPU, sensors, and more, all in one convenient tool.