Capacitor iOS Plugin Guide
Building Capacitor plugins for iOS involves writing Swift (or Objective-C) to interface with Apple's iOS SDKs.
Capacitor embraces standard iOS development tools for building iOS plugins. We believe that using Swift (or, Objective-C) directly will make it easier to use existing solutions on Stack Overflow, share work with existing native developers, and use platform features as soon as they are made available.
Getting Started
To get started, first generate a plugin as shown in the Getting Started section of the Plugin guide.
Next, open your-plugin/ios/Plugin.xcworkspace
in Xcode.
Building your Plugin in Swift
A Capacitor plugin for iOS is a simple Swift class that extends CAPPlugin
and
has some exported methods that will be callable from JavaScript.
Once your plugin is generated, you can start editing it by opening Plugin.swift
.
Simple Example
In the generated example, there is a simple echo plugin with an echo
function that simply returns a value that it was given.
This example demonstrates a few core components of Capacitor plugins: receiving data from a Plugin Call, and returning data back to the caller:
Plugin.swift
import Capacitor
@objc(MyPlugin)
public class MyPlugin: CAPPlugin {
@objc override public func load() {
// Called when the plugin is first constructed in the bridge
}
@objc func echo(_ call: CAPPluginCall) {
let value = call.getString("value") ?? ""
call.resolve([
"value": value
])
}
}
Accessing Called Data
Each plugin method receives an instance of CAPPluginCall
containing all the information of the plugin method invocation from the client.
A client can send any data that can be JSON serialized, such as numbers, text, booleans, objects, and arrays. This data
is accessible on the options
field of the call instance, or by using convenience methods such as getString
or getObject
.
For example, here is how you'd get data passed to your method:
@objc func storeContact(_ call: CAPPluginCall) {
let name = call.getString("yourName") ?? "default name"
let address = call.getObject("address") ?? [:]
let isAwesome = call.getBool("isAwesome") ?? false
guard let id = call.options["id"] as? String else {
call.reject("Must provide an id")
return
}
// ...
call.resolve()
}
Notice the various ways data can be accessed on the CAPPluginCall
instance, including how to require
options using guard
.
Returning Data Back
A plugin call can succeed or fail. For calls using promises (most common), succeeding corresponds to calling resolve
on the Promise, and failure calling reject
. For those using callbacks, a succeeding will call the success callback or the error callback if failing.
The resolve
method of CAPPluginCall
takes a dictionary and supports JSON-serializable data types. Here's an example of returning data back to the client:
call.resolve([
"added": true,
"info": [
"id": id
]
])
To fail, or reject a call, call call.reject
, passing an error string and (optionally) an Error
instance and extra data back:
call.reject(error.localizedDescription, error, [
"item1": true
])
Adding Initialization Logic
Plugins can override the load
method to run some code when the plugin is first initialized:
@objc(MyPlugin)
public class MyPlugin: CAPPlugin {
@objc override public func load() {
// Called when the plugin is first constructed in the bridge
}
}
Presenting Native Screens
To present a Native Screen over the Capacitor screen we need to acces the Capacitor's View Controller.
To access the Capacitor's View Controller, we have to use the CAPBridge
object available on CAPPlugin
class.
We can use the UIViewController
to present Native View Controllers over it like this:
DispatchQueue.main.async {
self.bridge.viewController.present(ourCustomViewController, animated: true, completion: nil)
}
Using DispatchQueue.main.async
makes your view render from the main thread instead of a background thread. Removing this can cause unexpected results.
On iPad devices you can also present UIPopovers
, to do so, we provide a helper function to show it centered.
self.setCenteredPopover(ourCustomViewController)
self.bridge.viewController.present(ourCustomViewController, animated: true, completion: nil)
Events
Capacitor Plugins can emit App events and Plugin events