iOS Quickstart (beta)
You will learn the following:
- Create a new Xcode project
- Install the Clerk iOS SDK
- Configure
Clerk
with your Publishable Key - Use Clerk to enable users to sign in and out of your application
Before you start
Disable bot protection
Bot protection is enabled by default for all Clerk apps. However, it is not supported in native apps.
To turn off bot protection:
- In the Clerk Dashboard, navigate to the Attack protection page.
- Disable Bot sign-up protection.
Create an iOS Project
To get started using Clerk with iOS, create a new project in Xcode. Select SwiftUI as your interface and Swift as your language. See the Xcode documentation for more information.
Install the Clerk iOS SDK
Follow the Swift Package Manager instructions to install Clerk as a dependency. When prompted for the package URL, enter https://github.com/clerk/clerk-ios. Be sure to add the package to your target.
Load Clerk
To use Clerk in your app, you must first configure and load Clerk
.
- Inside your new project in Xcode, open your
@main
app file. - Import
Clerk
. - Create a reference to the shared
Clerk
instance. - Replace
ContentView()
with the belowZStack
. - Inject your reference to the shared
clerk
instance into the environment. - Attach a
.task
modifier to the newZStack
. In the body of the task, configureclerk
with your Publishable Key, and then loadclerk
. You can get your Publishable Key from the API keys page in the Clerk Dashboard.
import SwiftUI
import Clerk
@main
struct ClerkQuickstartApp: App {
private var clerk = Clerk.shared
var body: some Scene {
WindowGroup {
ZStack {
if clerk.isLoaded {
ContentView()
} else {
ProgressView()
}
}
.environment(clerk)
.task {
clerk.configure(publishableKey: "YOUR_PUBLISHABLE_KEY")
try? await clerk.load()
}
}
}
}
Conditionally render content
To render content based on whether a user is authenticated or not:
- Open your
ContentView
file. - Import
Clerk
. - Access the shared
Clerk
instance that you injected into the environment in the previous step. - Replace the content of the view body with a conditional that checks for a
clerk.user
.
import SwiftUI
import Clerk
struct ContentView: View {
@Environment(Clerk.self) private var clerk
var body: some View {
VStack {
if let user = clerk.user {
Text("Hello, \(user.id)")
} else {
Text("You are signed out")
}
}
}
}
Create views for sign-up and sign-in
SignUpView
The following example creates a SignUpView
that allows users to sign up using their email address and password, and sends an email verification code to confirm their email address.
import SwiftUI
import Clerk
struct SignUpView: View {
@State private var email = ""
@State private var password = ""
@State private var code = ""
@State private var isVerifying = false
var body: some View {
VStack {
Text("Sign Up")
if isVerifying {
TextField("Code", text: $code)
Button("Verify") {
Task { await verify(code: code) }
}
} else {
TextField("Email", text: $email)
SecureField("Password", text: $password)
Button("Continue") {
Task { await signUp(email: email, password: password) }
}
}
}
.padding()
}
}
extension SignUpView {
func signUp(email: String, password: String) async {
do {
let signUp = try await SignUp.create(
strategy: .standard(emailAddress: email, password: password)
)
try await signUp.prepareVerification(strategy: .emailCode)
isVerifying = true
} catch {
dump(error)
}
}
func verify(code: String) async {
do {
guard let signUp = Clerk.shared.client?.signUp else {
isVerifying = false
return
}
try await signUp.attemptVerification(.emailCode(code: code))
} catch {
dump(error)
}
}
}
SignInView
The following example creates a SignInView
that allows users to sign in using their email address and password.
import SwiftUI
import Clerk
struct SignInView: View {
@State private var email = ""
@State private var password = ""
var body: some View {
VStack {
Text("Sign In")
TextField("Email", text: $email)
SecureField("Password", text: $password)
Button("Continue") {
Task { await submit(email: email, password: password) }
}
}
.padding()
}
}
extension SignInView {
func submit(email: String, password: String) async {
do {
try await SignIn.create(
strategy: .identifier(email, password: password)
)
} catch {
dump(error)
}
}
}
SignUpOrSignInView
Finally, create a SignUpOrSignInView
container view that allows users to switch between sign up and sign in.
import SwiftUI
struct SignUpOrSignInView: View {
@State private var isSignUp = true
var body: some View {
ScrollView {
if isSignUp {
SignUpView()
} else {
SignInView()
}
Button {
isSignUp.toggle()
} label: {
if isSignUp {
Text("Already have an account? Sign In")
} else {
Text("Don't have an account? Sign Up")
}
}
.padding()
}
}
}
Allow users to sign up or sign in
Go back to your ContentView
and render your newly created SignUpOrSignInView
when the user isn't signed in.
import SwiftUI
import Clerk
struct ContentView: View {
@Environment(Clerk.self) private var clerk
var body: some View {
VStack {
if let user = clerk.user {
Text("Hello, \(user.id)")
} else {
SignUpOrSignInView()
}
}
}
}
Allow users to sign out
Finally, provide users with a way to sign out of your app:
- Open your
ContentView
. - Add a button that ends a user's session.
import SwiftUI
import Clerk
struct ContentView: View {
@Environment(Clerk.self) private var clerk
var body: some View {
VStack {
if let user = clerk.user {
Text("Hello, \(user.id)")
Button("Sign Out") {
Task { try? await clerk.signOut() }
}
} else {
SignUpOrSignInView()
}
}
}
}
Feedback
Last updated on