⌘K

Swift block compiler

Nativeblocks provides compiler to connect any codes with its core SDK

The Nativeblocks compiler is a tool that generates server-driven blocks and actions based on Swift code. It produces JSON and Swift files for each block and action, preparing them for upload to Nativeblocks servers.

How it works

If your project uses its own 'Package.swift' file, you can add NativeblocksCompiler as a dependency there. Add NativeblocksCompiler to your dependencies list

dependencies: [
    .package(
        url: "https://github.com/nativeblocks/nativeblocks-compiler-ios.git",
        .upToNextMajor(from: "1.1.0")
    ),
],

Any targets in your application that will use NativeblocksCompiler need to have a dependency on the Nativeblocks product.

.target(
    name: "MyApp",
    dependencies: [
        .product(name: "NativeblocksCompiler", package: "nativeblocks-compiler-ios")
    ]
)

Usage

Blocks are composable functions that can be visually edited and configured within a Nativeblocks Studio. These annotations provide metadata and define configurable properties, slots, and events for your composable, making them usable as building blocks in a visual editor.

@NativeBlock

Purpose: Marks a composable function as a block.

Parameters:

  • name: The display name of the block in the visual editor.
  • keyType: A unique key used to identify the block type.
  • description: A brief description of the block's functionality.

Example:

@NativeBlock(name : "Custom button", keyType : "CUSTOM_BUTTON", description : "This is a button")

@NativeBlockProp

Purpose: Defines a configurable property for the block.

Parameters:

  • description: (Optional) A description of the property.
  • valuePicker: (Optional) Specifies the type of UI element used to edit the property (e.g., dropdown, text field).
  • valuePickerGroup: (Optional) Specifies the group name of the property to group all related properties.
  • valuePickerOptions: (Optional) Provides options for dropdown value pickers.

Example:

@NativeBlockProp(
    description : "Button size",
    valuePicker : NativeBlockValuePicker.DROPDOWN,
    valuePickerOptions : [
        NativeBlockValuePickerOption(" S", "Small"),
        NativeBlockValuePickerOption(" M", "Medium"),
        NativeBlockValuePickerOption(" L", "Large")
    ]
)

@NativeBlockData

Purpose: Marks a parameter as a data input for the block. This data can be provided directly from frame screen's variables.

Parameters:

  • description: (Optional) A description of the data input.

Example:

@NativeBlockData(description : "Button text")

@NativeBlockSlot

Purpose: Defines a slot where other blocks can be inserted.This enables nesting and composition of blocks.

Parameters:

  • description: (Optional) A description of the slot.

Example:

@NativeBlockSlot(description : "Button leading icon")

@NativeBlockEvent

Purpose: Defines an event that the block can trigger, such as a click or value change.

Parameters:

  • description: (Optional) A description of the event.

Example:

@NativeBlockEvent(description : "Button on click")

This example demonstrates a simple button block with configurable properties, slots for icons, and a click event.

@NativeBlock(
    name: "Custom button",
    keyType: "CUSTOM_BUTTON",
    description: "This is a button"
)
struct CustomButton: View {
    @NativeBlockData(description: "Button text")
    var text: String
    @NativeBlockProp(valuePicker: NativeBlockValuePicker.COLOR_PICKER)
    var background: String = "#ffffffff"
    @NativeBlockProp(
        description: "Button size",
        valuePicker: NativeBlockValuePicker.DROPDOWN,
        valuePickerOptions: [
            NativeBlockValuePickerOption("S", "Small"),
            NativeBlockValuePickerOption("M", "Medium"),
            NativeBlockValuePickerOption("L", "Large"),
        ]
    )
    var size: String = "S"
    @NativeBlockSlot(description: "Button leading icon")
    var onLeadingIcon: () -> AnyView
    @NativeBlockSlot(description: "Button trailing icon")
    var onTrailingIcon: (() -> AnyView)? = nil
    @NativeBlockEvent(description: "Button on click")
    var onClick: (() -> Void)?

    var body: some View {
        Button(action: {
            onClick?()
        }) {
            HStack(spacing: 8) {
                onLeadingIcon()
                Text(text)
                    .font(.system(size: textSize))
                    .padding(padding)
                if let trailingIcon = onTrailingIcon {
                    trailingIcon()
                }
            }
        }
        .buttonStyle(PlainButtonStyle())
        .background(Color(hex: background))
        .cornerRadius(24)
    }

    private var padding: EdgeInsets {
        switch size {
        case "M":
            return EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12)
        case "L":
            return EdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16)
        default:  // "S"
            return EdgeInsets(top: 4, leading: 4, bottom: 4, trailing: 4)
        }
    }

    private var textSize: CGFloat {
        switch size {
        case "M":
            return 22
        case "L":
            return 32
        default:  // "S"
            return 16
        }
    }
}

Generated files

After providing annotations for blocks and actions, you can use the 'GenerateProvider' plugin to generate Swift code. These can then be initialized in App or via dependency injection

Note: The prefix for the provider name comes from the target name that was selected. In this case, since we provided "MyApp," the compiler generates with the "MyApp" prefix.

MyAppBlockProvider.provideBlocks()