8.7 版本发布—WinterCG 兼容性第一部分
了解更多

在 GitHub 上查看

@nativescript/swift-ui

在 NativeScript 中使用 SwiftUI。

内容

安装

cli
npm install @nativescript/swift-ui

注意

您需要至少将目标设置为 iOS 13。

例如,您可以将此行添加到您的 App_Resources/iOS/build.xcconfig

IPHONEOS_DEPLOYMENT_TARGET = 13.0

使用

SwiftUI Source Files Example

1. 创建您的 SwiftUI 视图

这可以是您想要创建的任何 SwiftUI 视图。

swift
import SwiftUI

struct SampleView: View {

  var body: some View {
    VStack {
      Text("Hello World")
        .padding()
    }
  }
}

2. 创建您的 SwiftUI 视图提供程序

这将为您的 SwiftUI 准备双向数据绑定到 NativeScript,并遵循插件的 SwiftUIProvider 协议来标准化所有 SwiftUI 绑定。

ts
import SwiftUI

@objc
class SampleViewProvider: UIViewController, SwiftUIProvider {

  // MARK: INIT

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }

  required public init() {
    super.init(nibName: nil, bundle: nil)
  }

  public override func viewDidLoad() {
    super.viewDidLoad()
    setupSwiftUIView(content: swiftUIView)
  }

  // MARK: PRIVATE

  private var swiftUIView = SampleView()

  /// Receive data from NativeScript
  func updateData(data: NSDictionary) {
      // can be empty
  }

  /// Allow sending of data to NativeScript
  var onEvent: ((NSDictionary) -> ())?
}

3. 使用标识符注册您的 SwiftUI 并将其用于标记

这可以在引导文件(通常为 app.tsmain.ts)或需要它的视图组件中完成。

核心

typescript
import { registerSwiftUI, UIDataDriver } from '@nativescript/swift-ui'

// A. You can generate types for your own Swift Provider with 'ns typings ios'
// B. Otherwise you can ignore by declaring the class name you know you provided
declare const SampleViewProvider: any

registerSwiftUI(
  'sampleView',
  (view) => new UIDataDriver(SampleViewProvider.alloc().init(), view)
)

registerSwiftUI(
  'barChart',
  (view) => new UIDataDriver(BarChartProvider.alloc().init(), view)
)

然后将其插入任何布局,如下所示

xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page" xmlns:sw="@nativescript/swift-ui">
  <StackLayout>
    <sw:SwiftUI swiftId="sampleView" height="150" />
  </StackLayout>
</Page>

生成类型

  1. 要为您的 SwiftUI 代码生成类型,请运行 ns typings ios

  2. typings/x86_64 中找到 objc!nsswiftsupport.d.ts 文件,并在 references.d.ts 中引用它。

SwiftUI 与 Angular

注册 SwiftUI 如下

ts
import { registerElement } from '@nativescript/angular'
import { SwiftUI } from '@nativescript/swift-ui'

registerElement('SwiftUI', () => SwiftUI)

registerSwiftUI(
  'sampleView',
  (view) => new UIDataDriver(SampleViewProvider.alloc().init(), view)
)
registerSwiftUI(
  'barChart',
  (view) => new UIDataDriver(BarChartProvider.alloc().init(), view)
)

现在可以在任何 Angular 组件中使用它,例如

html
<StackLayout class="p-20">
  <SwiftUI swiftId="sampleView" height="150"></SwiftUI>
</StackLayout>

SwiftUI 与 Vue

注册 SwiftUI 如下

ts
registerElement('SwiftUIView', () => require('@nativescript/swift-ui').SwiftUI)

registerSwiftUI(
  'sampleView',
  (view) => new UIDataDriver(SampleViewProvider.alloc().init(), view)
)
registerSwiftUI(
  'barChart',
  (view) => new UIDataDriver(BarChartProvider.alloc().init(), view)
)

然后在标记中使用它,如下所示

xml
<StackLayout>

  <SwiftUIView swiftId="sampleView" height="200" />
  <SwiftUIView height="500" swiftId="barChart" margin="30" />

</StackLayout>

SwiftUI 与 React

注册 SwiftUI 如下

ts
registerSwiftUI(
  'sampleView',
  (view) => new UIDataDriver(SampleViewProvider.alloc().init(), view)
)

registerSwiftUI(
  'barChart',
  (view) => new UIDataDriver(BarChartProvider.alloc().init(), view)
)

interface SwiftUIViewAttributes extends ViewAttributes {
  swiftId: string
}

declare global {
  module JSX {
    interface IntrinsicElements {
      swiftUIView: NativeScriptProps<SwiftUIViewAttributes, SwiftUI>
    }
  }
}

registerElement('swiftUIView', () => require('@nativescript/swift-ui').SwiftUI)

然后在标记中使用它,如下所示

xml
<stackLayout>

  <swiftUIView swiftId="sampleView" height="200" />
  <swiftUIView height="500" swiftId="barChart" margin="30" />

</stackLayout>

打开多个场景

当为您的 NativeScript 应用使用 SwiftUI 应用生命周期设置时,默认情况下使用 visionOS 开发,您可以在 Info.plist 中使用以下内容启用多个场景

xml
<key>UIApplicationSceneManifest</key>
<dict>
  <key>UIApplicationPreferredDefaultSceneSessionRole</key>
  <string>UIWindowSceneSessionRoleApplication</string>
  <key>UIApplicationSupportsMultipleScenes</key>
  <true/>
  <key>UISceneConfigurations</key>
  <dict/>
</dict>

您现在可以使用 WindowManager(用于标准窗口)或 XR(用于沉浸式空间)与多个场景进行交互,例如

swift
@main
struct NativeScriptApp: App {
  @State private var immersionStyle: ImmersionStyle = .mixed

  var body: some Scene {
    NativeScriptMainWindow()

    WindowGroup(id: "NeatView") {
        NeatView()
    }
    .windowStyle(.plain)

    ImmersiveSpace(id: "NeatImmersive") {
        NeatImmersive()
    }
    .immersionStyle(selection: $immersionStyle, in: .mixed, .full)
  }
}

您可以使用以下方法打开 WindowGroup

ts
import { WindowManager } from "@nativescript/swift-ui";

WindowManager.getWindow("NeatView").open();
});

您可以使用以下方法打开 ImmersiveSpace

ts
import { XR } from '@nativescript/swift-ui'

XR.requestSession('NeatImmersive')

您可以使用以下方法更新任一场景:

ts
import { WindowManager } from '@nativescript/swift-ui'

// Option A: inline
WindowManager.getWindow('NeatView').update({
  title: 'Updated Title',
})

// Option B: reference
const neatView = WindowManager.getWindow('NeatView')

neatView.update({
  title: 'Updated Title',
})

// Both options work with XR/Immersive Spaces as well, for example:
WindowManager.getWindow('NeatImmersive').update({
  salutation: 'Hello World',
})

将上下文数据传递到场景

您可以在 SwiftUI 中使用 onReceive 修饰符来处理传递到窗口的任何数据。

例如,每当调用 WindowManager.getWindow("Window_ID").update(...) 时,都会分派一个通知,可以获取该通知以处理数据

swift
struct NeatView: View {
  @State var context: NativeScriptWindowContext?

  var body: some View {
    ZStack {
      // more neat views here
    }.onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("NativeScriptWindowUpdate")), perform: { obj in
      context = NativeScriptWindowFactory.shared.getContextForId(id: "NeatView")

      let title = context!.data["title"] as! String

      // use your updated title!
    })
  }
}

关闭窗口

对于已打开的窗口,WindowManager.getWindow("NeatView").close() 将关闭它。

对于已打开的沉浸式空间,XR.endSession() 将关闭它。

鸣谢

  • WindowManager 和 XR API 是与 Callstack 团队共同建立的。感谢:Oskar Kwaśniewski
Valor Software

NativeScript 自豪地得到 Valor Software 作为官方合作伙伴的支持。我们很自豪能够在所有 NativeScript 方面提供指导、咨询和开发帮助。

联系 Valor 获取帮助.

许可证

MIT