On this page

Qt Bridges - Swift

Introduction

Qt Bridge for Swift is a bridge between Swift and QML, designed to write application logic in Swift while using Qt Quick for the UI. Bridging mechanism is based on Swift and C++ interoperability.

Qt Bridge for Swift is intended for Apple developers who want to experiment with Qt and/or QML without committing to a full C++ application. The repository includes example applications and Xcode templates that demonstrate the recommended project structure, how to model data and logic in Swift, and how to connect those models to QML views.

Supported platforms

Currently, only macOS (Apple Silicon) is supported, with plans to extend support in the future.

Prerequisites

Installing Qt Bridge

Qt Bridge is distributed as a Swift Package Manager package. You can add it to your project as a package dependency using either a local package reference or the repository URL.

Importing Qt Bridge as a remote package

Add via Xcode

  1. In Xcode, select FileAdd Package Dependencies.
  2. Enter https://github.com/qt/qtbridge-swift
  3. Enable Swift-C++ interoperability:
    1. Go to the target's Build Settings.
    2. Switch the filter to All + Combined.
    3. Search for Interoperability.
    4. Under Swift Compiler - Language, set C++ and Objective-C Interoperability mode to C++/Objective-C++.

Add via Package.swift

  1. Specify the Qt Bridge package URL in the dependencies section.
  2. Link QtBridge product to your target.
  3. Enable Swift-C++ interoperability in swiftSettings with .interoperabilityMode(.Cxx) mode.
dependencies: [
    .package(url: "https://github.com/qt/qtbridge-swift", exact: "0.1.0-alpha")
],
targets: [
    .target(
        name: "MyApp",
        dependencies: [
            .product(name: "QtBridge", package: "qtbridge-swift")
        ],
        swiftSettings: [
            .interoperabilityMode(.Cxx)
        ]
    )
]

Importing Qt Bridge as a local package

Firstly, clone the Qt Bridge for Swift repo:

git clone https://github.com/qt/qtbridge-swift
cd qtbridge-swift
git checkout 0.1.0-alpha

Add via Xcode

  1. In Xcode, select FileAdd Package Dependencies.
  2. Click the *Add Local* button and select the folder that contains cloned Qt Bridge repo.
  3. Enable Swift-C++ interoperability:
    1. Go to the target's Build Settings.
    2. Switch the filter to All + Combined.
    3. Search for Interoperability.
    4. Under Swift Compiler - Language, set C++ and Objective-C Interoperability mode to C++/Objective-C++.

Add via Package.swift

  1. Specify a path to the cloned Qt Bridge repo in the dependencies section.
  2. Link QtBridge product to your target.
  3. Enable Swift-C++ interoperability in swiftSettings with .interoperabilityMode(.Cxx) mode.
dependencies: [
    .package(path: "path/to/qtbridge-swift")
],
targets: [
    .target(
        name: "MyApp",
        dependencies: [
            .product(name: "QtBridge", package: "qtbridge-swift")
        ],
        swiftSettings: [
            .interoperabilityMode(.Cxx)
        ]
    )
]

Disable Library Validation Entitlement

When you use a Team in Xcode and enable automatic signing, Xcode may enable the Hardened Runtime for the generated macOS app target. With Hardened Runtime enabled, macOS enforces Library Validation, which restricts the app to loading only system libraries and libraries signed with a compatible signature. Qt Bridge loads additional Qt frameworks at runtime, and this can cause the app to fail to launch when library validation is enabled.

To fix this:

  1. Open the Signing & Capabilities tab.
  2. Select your app target.
  3. Expand Hardened Runtime.
  4. Manually chech Disable Library Validation.

Alternatively, you can disable Hardened Runtime entirely by clicking Delete next to it, but disabling Library Validation alone is sufficient.

Running examples

The Examples directory contains simple projects implemented with Qt Bridge. For instance, to build and run MinimalApp:

cd qtbridge-swift/Examples/MinimalApp

xcodebuild \
-project MinimalApp.xcodeproj \
-scheme MinimalApp \
-destination 'platform=macOS' \
-derivedDataPath build \
build

open build/Build/Products/Debug/MinimalApp.app

Using Xcode templates

The Templates directory contains:

  • a project template for starting a new Swift + QML macOS application
  • file templates for adding Swift models and QML views

Installing the templates into Xcode

Copy the Templates folder into ~/Library/Developer/Xcode/Templates/.

Creating a new project from the Qt Bridge project template

  1. Open Xcode.
  2. Choose Create New Project...
  3. Scroll down to Qt Bridge section.
  4. Select the Qt Bridge project template and click Next.
  5. Fill in the template options:
    • Product Name – the name of the application (also used for the target name and bundle name).
    • Organization Identifier – a reverse-DNS identifier such as com.example.
    • Model Type Name – the Swift type used as the backend model, for example MyModel.
    • QML File Name – the base name of the initial QML file, without the .qml extension (for example main or myView).
    • Model Context Name – the name under which the model is exposed to QML, usually in lowerCamelCase (for example myModel).
    • Choose a location for the project and click Create.
  6. The generated project will contain:
    • an application entry point with @main
    • a Swift model type with the name you provided
    • a QML file with the chosen base name, already included in the app’s bundle resources
    • a macOS app target with Swift/C++ interoperability enabled
  7. The project template sets up the application structure, but you still need to add the Qt Bridge as a package dependency.

Running the example application

The generated project may fail to launch if Hardened Runtime is enabled because Qt Bridge dynamically loads Qt frameworks at runtime. To fix this, you need to disable Library Validation. For detailed instructions, see Disable Library Validation Entitlement.

At this point, the example application is ready to run. You can do so, by pressing the Run button. The project template configures the basic build settings and target configuration. For more advanced configuration, you can adjust Build Settings in the project navigator.

Adding a new file using file templates

Once the file templates are installed, they appear in the template explorer dialog under the Qt Bridge section.

  1. In the project navigator, select where you want to create the new file.
  2. Choose FileNewFile from Template...
  3. In the template chooser, scroll down until you find the Qt Bridge group.
  4. Select either the Backend Model or QML View template and click Next.
  5. Enter a model name for the Backend Model, or a file name for the QML file.

The generated Swift file will contain a class with the @QtBridgeable macro attached and a simple greeting function. The generated QML file will contain "Hello from Qt Bridges!" text that will be displayed in the app's window. Make sure that new QML files are included in the app target’s Copy Bundle Resources under Build Phases so that they are copied into the app bundle when you build.

API Overview

Classes and Annotations

QApp

In Qt Bridge for Swift, you declare the application's entry point by defining a type that conforms to the QApp protocol and marking that type with the @main attribute. QApp provides a default static main() implementation, which is invoked by the Swift runtime at launch to start the application. To conform to QApp, provide qmlFileName (without .qml) and initialProperties, where initialProperties is a dictionary of QML initial property names mapped to Swift objects that are exposed to QML. Only Swift types annotated with @QtBridgeable class macro are supported.

import QtBridge

@main
struct MyApp: QApp {
    let qmlFileName: String = "main"
    var initialProperties: [String : QtBridge.QObjectBuildable] = [
        "myModel" : MyModel()
    ]
}

@QtBridgeable

@QtBridgeable is a required type macro for any Swift class that should be exposed to QML. Only classes marked with this macro can be bridged into QML.

When applied, the macro:

  • Adds conformance to QObjectBuildable
  • Generates all required integration code
  • Inspects the class’s public API and exposes supported members to QML

A property is automatically exposed to QML if it meets all of the following requirements:

  • It is public.
  • It is a stored property.
  • It is an instance property.
  • It has an explicitly specified type, and the type is one of the supported types:
    • Int
    • UInt
    • Double
    • Float
    • String
    • Bool
    • [String]
    • QListModel<T>

Eligible properties are automatically annotated with @QtTracked and become available in QML.

A method is automatically exposed to QML if it meets all of the following requirements:

  • It is public.
  • It is an instance method.

To prevent a property or method from being exposed to QML, annotate it with the @QtIgnored member macro.

@QtTracked

This macro is automatically added to supported properties when the property’s type is explicitly specified.

To expose a property whose type is another Swift class, @QtTracked must be added manually. The referenced Swift class must also be marked with the appropriate macro; otherwise, this will result in compile-time errors.

@QtBridgeable
public class Nested {
    public var name: String = ""
}

@QtBridgeable
public class MyModel {
    @QtTracked public var nestedType: Nested = Nested()
}

This macro adds didSet observers to non-constant properties. When a property value changes, QML engine is notified automatically.

@QtIgnored

@QtIgnored is a member macro used to prevent a property or method from being exposed to QML.

When applied, the annotated member is excluded from the code generated by @QtBridgeable, even if it would otherwise be eligible for export.

@QtBridgeable
public class Model {
    @QtIgnored
    public var internalId: Int = 42
}

QListModel<T>

QListModel<T> is a Swift container designed to make a list of supported values available to QML views, so QML can show the items, read their fields and stay in sync when the list changes. When you modify the model through the container operations (append, replaceSubrange, remove, etc.), the model emits the appropriate change notifications so views update automatically. The item type T must be either one of the supported value types (Int, UInt, Bool, Double, Float, String, [String]), or a custom type annotated with @QtBridgeable macro.

Example usage with basic type:

import QtBridge

@QtBridgeable
public class ListModel {
    var list: QListModel<String> = ["test string"]
}

Example usage with custom type:

import QtBridge

@QtBridgeable
public class Contact {
    var name: String
    var phoneNo: String

    public init(name: String, phoneNo: String) {
        self.name = name
        self.phoneNo = phoneNo
    }
}

@QtBridgeable
public class PhoneBook {
    public var phoneBook: QListModel<Contact> = []
}

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.