Skip to main content

Getting started with iOS

Libraries

Step 1: Install the Skima library, which has all the Core logic of the framework:

Podfile
pod 'Skima'

Step 2: Create custom widgets or use some UI library. In our case we will use the SkimaStandardUI:

Podfile
pod 'SkimaStandardUI'

Step 3: Create custom actions or use any Actions library. In our case we will use the SkimaStandardActions:

Podfile
pod 'SkimaStandardActions'

Done! With these three libraries you already have everything installed!!

Code in your app

Register modules

Both the Actions and Widgets modules must be registered in Skima. For this, in the AppDelegate place:

AppDelegate.swift
import Skima
import SkimaStandardUI
import SkimaStandardActions

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
WidgetsEngine.shared.registerOrReplace(SkimaStandardUI.self) // Here the Widgets module is registered
ActionsEngine.shared.registerOrReplace(SkimaStandardActions.self) // Here the Actions module is registered

return true
}

Create screens

To use a screen from a Skima contract we can use the SkimaViewController which receives in its constructor the url from which to download the contract:

let viewController = SkimaViewController(fromEndpoint: "https://...")

If what you want is to start the application from a contract you can place the following method in the SceneDelegate:

import Skima

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }

window = UIWindow(windowScene: scene)

let viewController = SkimaViewController(fromEndpoint: "https://...")
let navigationController = UINavigationController(rootViewController: viewController)
NavigationEngine.shared.setNavigationController(navigationController) // This tells Skima which navigationController to use for navigation
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
}

Test Screens

To quickly test that everything is ok you can use the following screen contract as a demo:

https://run.mocky.io/v3/f960b018-feca-4860-bcaf-b31b66bd95b7

Create your own Widgets

Each Widget has three parts: 1. props model, 2. widget's class, 3. Manipulators. So, lets create a simple Label widget as example!

Step 1: Create the props model

The props model is a struct that conform the WidgetPropsType protocol:

LabelProps.swift
import Skima

struct LabelProps: WidgetPropsType {
var text: String?
var fontSize: Double?
}

Step 2: Create the Widget class

The Widget class must conform the UIWidget protocol:

Label.swift
import UIKit
import Skima

class Label: UILabel, UIWidget {
static var manipulators: [ActionSchema] = []

var widget: Widget
private var props: LabelProps?

required init(from: widget Widget) {
self.widget = widget
self.props = widget.props as? LabelProps
super.init(frame: .zero)
configureView()
}

private func configureView() {
setText(text: props?.text)
setFontSize(props?.fontSize)
}

private func setText(text: String?) {
self.text = text
}

private func setFontSize(size: Double?) {
guard let _size = size else { return }
font = font.withSize(CGFloat(_size))
}
}

Step 3: Create the manipulators

The manipulators are Actions that are applied to a given Widget, for example to change its color, its content or its state.

To create a Widget manipulator we need to create a class that conform the WidgetManipulatorData protocol and include this class in the manipulators array of the Widget itself:

LabelManipulator.swift
import Skima

class LabelManipulator: WidgetManipulatorData {
var widgetId: String?
var type: String?
var value: String?

func execute(from scopes: [Scope]?) {
guard let _widgetId = widgetId,
let _widget = WidgetsEngine.shared.getWidgetBy(id: _widgetId, from: scopes) as? Label
else { return }

switch type {
case "change_text":
widget.setText(value)
default:
break
}
}

}

Then, back in the Widget class:

Label.swift
...
class Label: UILabel, UIWidget {
static var manipulators = [ActionSchema(type: "labelManipulation", actionData: LabelManipulator.self)]

...

That's it, you have created your own Skima Widget! Now there is only one step left...

Step 4: Registering the Widget in your app

Now we need to let Skima know the new Widget so we have to register it. To do that we have to code:

AppDelegate.swift
import Skima

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
WidgetsEngine.shared.registerOrReplace(WidgetSchema(type: "label", view: Label.self, props: LabelProps.self)) // Label is the new Widget
return true
}

We did it in the AppDelegate but you can do it wherever you want.

Step 5: Use the Widget from the BFF

Now we can use the new Widget with the following JSON:

{
"type": "label",
"id": "label_1",
"props": {
"text": "Hello Skima!",
"fontSize": 16
}
}

If we want to change its text we use the following action:

{
"type": "labelManipulation",
"data": {
"widgetId": "label_1",
"type": "change_text",
"value": "This is the new text"
}
}

Create your own Actions

Creating an Action is even simpler!

Step 1: Create the ActionData model

The ActionData struct will have the data of the action and its logic. It must conform the ActionDataType protocol:

CloseAppActionData.swift
import Skima

struct CloseAppActionData: ACtionDataType {
let consoleMessage: String?

func execute(from scopes: [Scope]?) {
print(consoleMessage)
NSApplication.shared.terminate(self)
}
}

Step 2: Register the Action in your app

Now we need to let Skima know the new Action so we have to register it. To do that we have to code:

AppDelegate.swift
import Skima

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
ActionsEngine.shared.registerOrReplace(ActionSchema(type: "close_app", CloseAppActionData: LabelProps.self)) // close_app is the new Widget
return true
}

We did it in the AppDelegate but you can do it wherever you want.

Step 3: Use the Action from the BFF

Now we can use the new Action with the following JSON:

{
"type": "close_app",
"data": {
"consoleMessage": "Closing the app..."
}
}