Skip to content

iOS

基于 Rust 的 Slint 应用程序可以交叉编译到 iOS,并在 iPhone、iPad 及其各自的 模拟器上运行。这是通过 Winit 后端 和

Skia 渲染器 实现的。

  • 一台运行 macOS 的电脑。
  • 最新安装的 Xcode。
  • Xcodegen。
  • Rust
  • Rust 设备端和模拟器工具链。运行 rustup target add aarch64-apple-ios 和 rustup target add aarch64-apple-ios-sim 来添加它们。

为现有的 Rust 应用程序添加 iOS 支持

Section titled “为现有的 Rust 应用程序添加 iOS 支持”

以下步骤假设你已经准备好一个使用 Slint 的 Rust 应用程序。如果你刚入门,请使用我们的 Slint Rust Template 让一个最小应用跑起来。

使用 XCode 构建、部署 iOS 应用程序并提交到 App Store。 使用 Xcodegen 从一份最简描述创建 Xcode 项目。

  1. 通过运行以下命令,验证你的应用程序能为 iOS 编译:
Terminal window
cargo build --target=aarch64-apple-ios
bash
  1. 创建一个名为 project.yml 的文件,内容如下:
name: My App
options:
bundleIdPrefix: com.company
settings:
ENABLE_USER_SCRIPT_SANDBOXING: NO
targets:
MyApp:
type: application
platform: iOS
deploymentTarget: '13.0'
info:
path: Info.plist
properties:
CADisableMinimumFrameDurationOnPhone: true
UILaunchScreen:
- ImageRespectSafeAreaInsets: false
UIApplicationSceneManifest:
UIApplicationSupportsMultipleScenes: false
UISceneConfigurations:
UIWindowSceneSessionRoleApplication:
- UISceneConfigurationName: Slint
UISceneDelegateClassName: SlintWindowSceneDelegate
sources: []
postCompileScripts:
- script: |
./build_for_ios_with_cargo.bash slint-rust-template
outputFileLists: $TARGET_BUILD_DIR/$EXECUTABLE_PATH
yml

根据需要调整名称、bundle id 和其他字段。

这个配置文件通过一个 shell 脚本把构建过程委托给 cargo。

CADisableMinimumFrameDurationOnPhone 条目让动画以屏幕的 完整刷新率运行。 没有它,即使 ProMotion 显示屏支持 120,iOS 也会把 iPhone 应用限制在每秒 60 帧。 iPad 不受影响。

UIApplicationSceneManifest 条目让应用选择使用 UIKit 的场景生命周期, 这是 iOS 27 所要求的:没有它的应用会启动失败。 SlintWindowSceneDelegate 是 Slint 的 winit 后端提供的场景委托, 它把 Slint 的窗口附加到 UIKit 所连接的场景。 保持该条目原样。 关于此要求的背景,请参见 Apple 的 TN3187。

  1. 在一个名为 build_for_ios_with_cargo.bash 的新文件中,粘贴以下脚本代码:
#!/usr/bin/env bash
# Copyright © SixtyFPS GmbH <info@slint.dev>
# SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
set -euvx
# Fix up PATH to work around https://github.com/rust-lang/rust/issues/80817 and add cargo.
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH:$HOME/.cargo/bin"
# based on https://github.com/mozilla/glean/blob/main/build-scripts/xc-universal-binary.sh
if [[ "$CONFIGURATION" != "Debug" ]]; then
CARGO_PROFILE=release
MAYBE_RELEASE=--release
else
CARGO_PROFILE=debug
MAYBE_RELEASE=
fi
# Build with debug info so a dSYM can be produced below. Release builds carry no
# debug info by default, which makes the archive fail validation with a missing
# dSYM for the (cargo-built) executable.
export CARGO_PROFILE_RELEASE_DEBUG="${CARGO_PROFILE_RELEASE_DEBUG:-1}"
# Make Cargo output cache files in Xcode's directories
export CARGO_TARGET_DIR="$DERIVED_FILE_DIR/cargo"
# Xcode Cloud exposes its build counter as CI_BUILD_NUMBER. Forward it as
# SLINT_BUILD_NUMBER so the viewer's idle screen can show which CI build it
# came from. Local Xcode builds don't set CI_BUILD_NUMBER, in which case we
# leave SLINT_BUILD_NUMBER unset and the idle screen omits the build line.
if [ -n "${CI_BUILD_NUMBER:-}" ]; then
export SLINT_BUILD_NUMBER="$CI_BUILD_NUMBER"
fi
IS_SIMULATOR=0
if [ "${LLVM_TARGET_TRIPLE_SUFFIX-}" = "-simulator" ]; then
IS_SIMULATOR=1
fi
executables=()
for arch in $ARCHS; do
case "$arch" in
arm64)
if [ $IS_SIMULATOR -eq 0 ]; then
CARGO_TARGET=aarch64-apple-ios
else
CARGO_TARGET=aarch64-apple-ios-sim
fi
;;
x86_64)
export CFLAGS_x86_64_apple_ios="-target x86_64-apple-ios"
CARGO_TARGET=x86_64-apple-ios
;;
esac
cargo build $MAYBE_RELEASE --target $CARGO_TARGET --bin "$1" "${@:2}"
executables+=("$DERIVED_FILE_DIR/cargo/$CARGO_TARGET/$CARGO_PROFILE/$1")
done
# Combine executables, and place them at the output path excepted by Xcode
lipo -create -output "$TARGET_BUILD_DIR/$EXECUTABLE_PATH" "${executables[@]}"
# Generate a dSYM for the executable into the folder Xcode collects dSYMs from
# for the archive. Xcode only produces dSYMs for what it compiles, not for this
# cargo-built binary, so without this the archive has no dSYM matching its UUID.
if [ -n "${DWARF_DSYM_FOLDER_PATH:-}" ] && [ -n "${DWARF_DSYM_FILE_NAME:-}" ]; then
mkdir -p "$DWARF_DSYM_FOLDER_PATH"
dsymutil "$TARGET_BUILD_DIR/$EXECUTABLE_PATH" -o "$DWARF_DSYM_FOLDER_PATH/$DWARF_DSYM_FILE_NAME"
fi
# Force code signing every run for device builds (non-simulator), unless code
# signing is disabled (e.g. unsigned archive builds with CODE_SIGNING_ALLOWED=NO).
if [ $IS_SIMULATOR -eq 0 ] && [ "${CODE_SIGNING_ALLOWED:-YES}" != "NO" ] && [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" ]; then
# Only pass --entitlements when the .xcent file is non-empty (needed for Xcode Cloud).
ENTITLEMENTS_FILE="${TARGET_TEMP_DIR}/${PRODUCT_NAME}.app.xcent"
if [ -s "$ENTITLEMENTS_FILE" ]; then
codesign --force --sign "${EXPANDED_CODE_SIGN_IDENTITY}" \
--entitlements "$ENTITLEMENTS_FILE" \
"${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}"
else
codesign --force --sign "${EXPANDED_CODE_SIGN_IDENTITY}" \
"${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}"
fi
fi
  1. 用 chmod +x build_for_ios_with_cargo.bash 使脚本可执行。

  2. 运行 xcodegen 创建 My App.xcodeproj,并在 Xcode 中打开它。现在你可以构建、部署和调试你的 iOS 应用程序。

在 iOS 模拟器中运行的 Slint 模板截图

© 2026 SixtyFPS GmbH