GitHub

一个类似 SwiftUI 的框架,用于在 Swift 中创建跨平台应用程序。

这个包仍然处于早期开发阶段,所以不要期望它非常有用或稳定。

注意:SwiftCrossUI 并不试图完美地复制 SwiftUI 的 API,因为 SwiftCrossUI 的目标是比 SwiftUI 更简单。然而,SwiftUI 的许多概念仍然可以借鉴。

社区

关于 SwiftCrossUI 的讨论现在在 SwiftCrossUI Discord 服务器 中进行(以前在 SwiftGtk Discord 服务器的一个频道中进行)。如果您想参与、讨论库或只是想了解最新进展,请随时加入

支持 SwiftCrossUI

如果您觉得 SwiftCrossUI 有用,请考虑成为赞助者来支持我。我将大部分空闲时间用于开源项目,每一笔赞助都帮助我投入更多时间为社区制作高质量的库和工具。

后端

SwiftCrossUI 拥有针对不同操作系统的各种后端。SwiftCrossUI 的优点在于您可以编写一次应用程序,使其在任何地方都看起来原生。因此,我建议使用 DefaultBackend,除非您有特殊限制。

如果您像示例一样使用 DefaultBackend,则可以通过将 SCUI_DEFAULT_BACKEND 环境变量设置为您想要的后端名称来在编译应用程序时覆盖默认值。当您想要测试应用程序的 Gtk 版本,同时使用 Mac 时,这可能非常有用。

示例

这是一个简单的示例应用程序,演示了 SwiftCrossUI 入门有多么容易

import SwiftCrossUI
// Import whichever backend you need
import DefaultBackend

@main
struct CounterApp: App {
    // You can explicitly provide your selected backend to SwiftCrossUI if you
    // want extra control. This allows you to configure the backend if the
    // backend has alternative initializers.
    //
    //  var backend = DefaultBackend()

    @State var count = 0

    var body: some Scene {
        WindowGroup("CounterApp") {
            HStack {
                Button("-") {
                    count -= 1
                }
                Text("Count: \(count)")
                Button("+") {
                  count += 1
                }
            }
            .padding(10)
        }
    }
}

要运行此示例,请运行以下命令

git clone https://github.com/stackotter/swift-cross-ui
cd swift-cross-ui/Examples
swift run CounterExample

其他示例

SwiftCrossUI 包含一些示例,用于演示其一些基本功能。

在其他后端上运行示例

所有示例都使用 DefaultBackend,因此在构建示例时,您可以简单地设置 SCUI_DEFAULT_BACKEND 环境变量来尝试各种后端(当然,这受限于各种后端与您的操作系统的兼容性)。

SCUI_DEFAULT_BACKEND=QtBackend swift run CounterExample

文档

这是文档站点。请记住,该项目仍处于早期开发阶段,一旦项目成熟一些,就会创建适当的文档和教程,否则我必须花费太多时间来保持文档的更新。

依赖项

  1. Swift 5.5 或更高版本
  2. Gtk 4(仅 GtkBackend 需要)
  3. clang(仅 Linux 上的 GtkBackend 需要)
  4. Qt5(仅 QtBackend 需要)

macOS:安装 Gtk 4

使用 HomeBrew 或您选择的软件包管理器安装 Gtk 4。

brew install pkg-config gtk4

如果您在尝试构建 swift-cross-ui 项目时遇到与 libffiFFI 相关的错误(可能是由于安装了 Xcode CLTs 引起的),请尝试运行以下命令来修补 libffi

sed -i '' 's/-I..includedir.//g' $(brew --prefix)/Library/Homebrew/os/mac/pkgconfig/*/libffi.pc

Linux:安装 Gtk 4 和 Clang

使用 apt 或您选择的软件包管理器安装 Gtk 4 和 Clang。在大多数基于 GNOME 的系统上,应该已经安装了 Gtk(尽管您应该验证它是否是 Gtk 4)。

sudo apt install libgtk-4-dev clang

如果您在尝试构建 swift-cross-ui 项目时遇到与找不到 gtk/gtk.h 相关的错误,请尝试重启您的计算机。这在某些情况下有效(尽管可能存在更优雅的解决方案)。

Windows(实验性):通过 vcpkg 安装 Gtk 4

使用 vcpkg 安装 Gtk 4 是在 Windows 上设置 SwiftCrossUI 的受支持方法。

安装 vcpkg

git clone https://github.com/microsoft/vcpkg C:\vcpkg
C:\vcpkg\bootstrap-vcpkg.bat

注意:由于 Gtk 构建系统的限制,将 vcpkg 安装到 C: 或任何其他驱动器的根目录非常重要。

全局安装 Gtk 4(推荐)

运行以下命令全局安装 Gtk 4。这可能需要 45 分钟或更长时间,具体取决于您的机器。在驱动器的根目录中运行此命令将确保 vcpkg 不会在清单模式下运行。

C:\vcpkg\vcpkg.exe install gtk --triplet x64-windows

安装完成后,您必须对您的环境变量进行以下更改

  1. PKG_CONFIG_PATH 环境变量设置为 C:\vcpkg\installed\x64-windows\lib\pkgconfig。这仅在构建时需要。
  2. C:\vcpkg\installed\x64-windows\bin 添加到您的 Path 环境变量。这仅在运行时需要。

如果全局安装失败,请尝试删除 C:\vcpkg 并重新开始,否则请向 vcpkg 存储库提交 issue,并通过 stackotter@stackotter.dev 告知我。

使用项目清单安装 Gtk 4(更不可靠)

注意:如果您的项目的绝对路径包含空格,则 vcpkg 可能会崩溃,全局安装将是更可靠的策略。

您可以在您的软件包工作区内安装 Gtk 4,以拥有软件包特定的依赖项存储。首先,在您的软件包根目录创建一个 vcpkg.json。您可以从此仓库下载 vcpkg.json 文件,或者自己创建它;

{
    "name": "swift-cross-ui",
    "version-string": "main",
    "dependencies": ["gtk"]
}

将目录更改为您的软件包根目录,然后运行以下命令来构建和安装依赖项。

C:\vcpkg\vcpkg.exe install --triplet x64-windows

安装完成后,您必须对您的环境变量进行以下更改

  1. PKG_CONFIG_PATH 环境变量设置为 PACKAGE_ROOT\vcpkg_installed\x64-windows\lib\pkgconfig,以允许 SwiftPM 使用已安装的软件包。
  2. C:\path\to\your\project\vcpkg_installed\x64-windows\bin 添加到您的 PATH 环境变量。

如果您遇到问题(可能与 libsass 相关),请尝试改为全局安装(见上文)。

分发 SwiftCrossUI 应用程序

vcpkg_installed\<triplet>\bin 包含在 Windows 上运行 SwiftCrossUI 应用程序所需的所有 DLL,但并非所有 DLL 都是必需的。

要确定哪些是必需的,您可以使用Dependencies 工具来检查编译后的可执行文件,并将所有 vcpkg 安装的 DLL 与可执行文件一起复制以进行分发。

安装 Qt5

# On macOS
brew install qt@5
brew link qt@5

# Linux with apt
sudo apt install qtcreator qtbase5-dev qt5-qmake cmake

用法

只需将 SwiftCrossUI 添加为您的 Package.swift 中的依赖项。请参阅下面的示例软件包清单

import PackageDescription

let package = Package(
  name: "Example",
  dependencies: [
    .package(url: "https://github.com/stackotter/swift-cross-ui", branch: "main")
  ],
  targets: [
    .executableTarget(
      name: "Example",
      dependencies: [
        .product(name: "SwiftCrossUI", package: "swift-cross-ui")
      ]
    )
  ]
)