Canva provides an SDK to adding the Canva Button to iOS apps. You can use this SDK to launch the Canva editor from within your app.
Here's how it works:
Your app can open the Canva editor in a browser window. The user then creates or edits a design. When the user clicks the Publish button, your app downloads the user's design as an image file.
This tutorial series explains how to add the Canva Button to an empty iOS app. Once you understand the workflow, adapt the steps to add the Canva Button to your existing app
Prerequisites
This tutorial assumes you have an API key to use the Canva Button. If you don't have one, sign up for an API key.
Step 1: Create an Xcode project
- Open Xcode.
- Select File > New > Project.
- Select iOS > App.
- Select Next.
- Select Interface > Storyboard.
- Select Life Cycle > UIKit App Delegate.
- Select Language > Swift.
- Select Next.
- Choose a location for the project.
Step 2: Install the Canva Button SDK
Carthage
Coming soon.
Cocoapods
-
Copy the following code snippet into the project's
Podfile
:use_frameworks!target 'YourApp' dopod 'Canva.DesignButton'endbash -
Run
pod update
.
Manual
Add the framework to the project
- Download and extract the
CanvaButton.tar.gz
file. You should have received this file from Canva. The archive contains aCanvaButton.framework
file, along with.bcsymbolmap
and.dSYM
files. - Drag the
CanvaButton.framework
file into the Xcode project. - In the Navigator, select the project.
- Under the Targets heading, select the target.
- Switch to the General tab.
- In the Frameworks, Libraries and Embedded content section, add the
CanvaButton.framework
file. - Set the Embed option to Embed & Sign.
Copy files at build time
- Switch to the Build Phases tab.
- Click the + button.
- Select New Copy Files Phase.
- Expand the Copy Files panel.
- Set the Destination to Products Directory.
- Add the
.bcsymbolmap
and.dSYM
files to the list of copied files.
Run a script at build time
-
Click the + button.
-
Select New Run Script Phase.
-
Expand the Run Script panel.
-
Copy the following command into the script editor:
bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/CanvaButton.framework/strip.sh" "${BUILT_PRODUCTS_DIR}"bash -
Enable For install builds only.
Step 3: Set up custom URL schemes
Canva uses custom URL schemes to send information from the Canva editor to your app. URL schemes are unique values that are tied to your Canva Button API key. Canva should have already provided you with this scheme.
To set up the custom URL schemes for your app:
- Open the
Info.plist
file. - Create a String property with a Key of
CanvaButtonScheme
. - Set the URL scheme as the value of the following properties:
- CanvaButtonScheme
- URL Types > Item 0 > URL Schemes > Item 0
Step 4: Handle custom URL schemes
The iOS SDK provides two functions for handling custom URL schemes:
isInternalURL
handleInternalURL
You can use these functions to execute behavior in response to the information that Canva sends to your app. The exact implementation on whether or not your app uses scenes.
With scenes
If your app uses scenes, import the CanvaButton
module into the SceneDelegate.swift
file:
import CanvaButton
Then copy the following code into the SceneDelegate
class:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {for context in URLContexts {if CanvaButton.isInternalURL(context.url) {CanvaButton.handleInternalURL(context.url)}}}
Without scenes
If your app doesn't use scenes, import the CanvaButton
module into the AppDelegate.swift
file:
import CanvaButton
Then copy the following code into the AppDelegate
class:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {if CanvaButton.isInternalURL(url) {CanvaButton.handleInternalURL(url)}return true}
Step 5: Implement the CanvaViewControllerDelegate
protocol
When a user opens and interacts with the Canva editor, the SDK sends information to your app. To receive this information, import the CanvaButton
module into the ViewController.swift
file:
import CanvaButton
Then copy the following code into the ViewController.swift
file:
extension ViewController: CanvaViewControllerDelegate {func canvaViewController(_ canvaViewController: CanvaViewController, didFailToLoadWithError error: Error) {print("Unable to load Canva editor.")print(error)}func canvaViewController(_ canvaViewController: CanvaViewController, didTerminateLoadingForDesignID designID: String?) {print("Unable to open design with an ID of \(designID ?? "nil").")}func canvaViewController(_ canvaViewController: CanvaViewController, didPublishDesignWithDesignID designID: String?, url: URL?) {print("Published a design with an ID of \(designID ?? "nil").")}func canvaViewDidFailPublish(forDesignID designID: String?, withError error: Error) {print("Unable to publish design with an ID of \(designID ?? "nil").")print(error)}func canvaViewController(_ canvaViewController: CanvaViewController, didFinishLoadingWithDesignID designID: String) {print("Opened a design with an ID of \(designID).")}}
This code extends the ViewController
class and implements the CanvaViewControllerDelegate
protocol.
Based on this change, the following methods run throughout the lifecycle of the app:
didFailToLoadWithError
didTerminateLoadingForDesignID
didPublishDesignWithDesignID
canvaViewDidFailPublish
didFinishLoadingWithDesignID
The behavior of these methods is explained throughout this tutorial.
Example
AppDelegate.swift
import UIKitimport CanvaButton@mainclass AppDelegate: UIResponder, UIApplicationDelegate {func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {if CanvaButton.isInternalURL(url) {CanvaButton.handleInternalURL(url)}return true}func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {return true}func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)}}
SceneDelegate.swift
import UIKitimport CanvaButtonclass SceneDelegate: UIResponder, UIWindowSceneDelegate {var window: UIWindow?func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {for context in URLContexts {if CanvaButton.isInternalURL(context.url) {CanvaButton.handleInternalURL(context.url)}}}func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {guard let _ = (scene as? UIWindowScene) else { return }}}
ViewController.swift
import UIKitimport CanvaButtonclass ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()}}extension ViewController: CanvaViewControllerDelegate {func canvaViewController(_ canvaViewController: CanvaViewController, didFailToLoadWithError error: Error) {print("Unable to load Canva editor.")print(error)}func canvaViewController(_ canvaViewController: CanvaViewController, didTerminateLoadingForDesignID designID: String?) {print("Unable to open design with an ID of \(designID ?? "nil").")}func canvaViewController(_ canvaViewController: CanvaViewController, didPublishDesignWithDesignID designID: String?, url: URL?) {print("Published a design with an ID of \(designID ?? "nil").")}func canvaViewDidFailPublish(forDesignID designID: String?, withError error: Error) {print("Unable to publish design with an ID of \(designID ?? "nil").")print(error)}func canvaViewController(_ canvaViewController: CanvaViewController, didFinishLoadingWithDesignID designID: String) {print("Opened a design with an ID of \(designID).")}}