# 从 SwiftUI 迁移

> View/@State→Component 映射与重写的表单，以及目标平台的差异。

Source: https://crossfly.dev/zh/docs/migrate/from-swiftui — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 从 SwiftUI 迁移

在 SwiftUI 中，`body` 是计算得出的，当 `@State` 变化时视图会**失效**。在 CrossFly 中你**装配
一次**并**变更**。请先阅读 [理念](/docs/migrate/overview)。

## 转换表
| SwiftUI | CrossFly |
|---|---|
| `View` / 计算得出的 `body` | 在 `onShow()` 中装配**一次**的 UI |
| `@State` / `@Binding` / `@ObservedObject` | 字段 + `repaint()`（无自动失效） |
| `VStack` / `HStack` / `ZStack` | `VerticalLayout` / `HorizontalLayout` / `RelativeLayout` |
| `Spacer()` | `Gap` / 分数（框架的 `Spacer` 已被**移除**） |
| `.padding()` | 样式中的 `ingap` |
| `List` | `VirtualListView` |
| `Text` | `Label` |
| `Button` | `Button` |
| `NavigationStack` / `.sheet` | `Window` 栈 / `ActionSheet` |
| `.alert` | `Alert` |
| `async` / `await` / `Task` | `Thread` + `Component.onUI(...)` |
| `Color` | `int 0xAARRGGBB` |

## 目标平台的差异
SwiftUI **只在 Apple 上**运行。CrossFly 是**一套 Java 代码库**，可在 iOS **和** Android、桌面端和
Web 上运行——所有平台使用同一份界面代码（参见 [平台](/docs/platforms)）。

## 之前/之后——表单
```swift
// SwiftUI
struct LoginView: View {
   @State private var email = ""
   var body: some View {
      VStack {
         TextField("E-mail", text: $email)
         Button("Entrar") { entrar(email) }
      }
   }
}
```
```java
// CrossFly
public class LoginScreen extends Window {
   @Override public void onShow() throws Exception {
      super.onShow();
      setLayout(new VerticalLayout());
      TextField email = new TextField().caption("E-mail");
      add(LAY_AUTO, email);
      Button entrar = new Button("Entrar");
      entrar.onAction(c -> entrar(email.getText()));   // 在提交时读取值（无 $binding）
      add(LAY_AUTO, entrar);
   }
}
```
> 没有 `$binding`：你在需要时**读取 `getText()`**（例如在 `onAction` 中），不存在
> 字段↔变量的自动绑定（参见 [文本字段](/docs/ui/forms-and-input/text-fields)）。

## 另请参阅
- [表单与输入](/docs/ui/forms-and-input) · [导航](/docs/ui/navigation)
