Swiftui for Nativecript简介
#javascript #ios #nativescript #swiftui

构建用户界面声明是网络社区广泛采用的东西,如今,按照这些原则构建了大型应用程序。例如,Google启动了Jetpack Compose,Apple在WWDC19宣布了SwiftUI,并获得了开发人员的极为积极回应。

Valor Software,我们总是对开发技术的新进步感到兴奋,并且我们是NativeScript的粉丝。我们与nStudio合作,为由NativeScript驱动的iOS应用提供有效且令人愉快的Swiftui集成。

在本文中,我们将演示如何在NativeScript中使用Swiftui来探索有趣的新可能性。

先决条件

  • macos catalina或更高的
  • Xcode 11或更高
  • iOS设备/模拟器运行iOS 13或更高版本

Swiftui概念

现代iOS开发主要使用Swift编程语言完成。 SwiftUi使用声明语法â``您说明用户界面应该做什么。

''

我建议服用官方的SwiftUI tour,以熟悉基本概念。

创建一个Antivescript应用程序

我们可以使用标准打字稿模板创建应用程序:

ns create swiftui --ts
cd swiftui

这将设置通常称为“香草”调味的nativesscript应用程序的内容。换句话说,它提供了基本的数据绑定功能和相当简单的设置。但是,我们将在这里介绍的内容适用于任何风味(Angular,React,Svelte,Vue等)。您可以通过以下内容通过Stackblitz进行更多探索:

Swiftui插件

安装SwiftUI plugin

npm install @nativescript/swift-ui

注意:您的最低iOS部署目标应至少为13。

您可以将此行添加到App_Resources/iOS/build.xcconfig

IPHONEOS_DEPLOYMENT_TARGET = 13.0;

Swiftui使用

a。创建您的swiftui

创建App_Resources/iOS/src/SampleView.swift

import SwiftUI

struct SampleView: View {

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

b。创建您的Swiftui提供商

这将为您的SwiftUi准备与Nativecript的双向数据绑定。

创建App_Resources/iOS/src/SampleViewProvider.swift

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) -> ())?
}

c。插入任何nativescript布局

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

d。通过SwiftID注册您的Swiftui

这可以在Nativecript应用程序的Bootstrap文件(通常是app.tsmain.ts)中完成。

  • app.ts
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)
);

您现在可以使用ns debug ios运行该应用程序。

使用Xcode开发您的Swiftui

运行一次项目后,您可以在Xcode中打开它,以使用Xcode IntelliSense的所有方便辅助。

例如,从项目的根目录中:

open platforms/ios/swiftui.xcworkspace

您会在TNSNativeSource文件夹下方找到您的.swift代码,如下所示...

Using Xcode to develop SwiftUI within context of NativeScript app

iOS预览


Basic View App Screenshot

先进的Swiftui集成

让我们通过连接数据绑定 + swiftui和nativecript之间的数据来深入研究。

创建Swiftui组件

这可以是您想在NativeScript中使用的任何Swiftui。

创建App_Resources/iOS/src/SampleView.swift

import SwiftUI

class ButtonProps: ObservableObject {
  @Published var count: Int = 0
  var incrementCount: (() -> Void)?
}

struct SampleView: View {

  @ObservedObject var props = ButtonProps()

  var body: some View {
      VStack(alignment: .center, spacing: 0) {
          HStack(alignment:.center) {
              Text("Count \(props.count)")
                  .padding()
                  .scaledToFill()
                  .minimumScaleFactor(0.5)
          }
          HStack(alignment: .center) {
              Button(action: {
                  self.props.incrementCount?()
              }) {
                  Image(systemName: "plus.circle.fill")
                      .foregroundColor(.white)
                      .padding()
                      .background(LinearGradient(
                          gradient: Gradient(
                              colors: [Color.purple, Color.pink]), startPoint: .top, endPoint: .bottom
                      ))
                      .clipShape(Circle())
              }
          }
      }
      .padding()
      .clipShape(Circle())
  }
}

创建App_Resources/iOS/src/SampleViewProvider.swift

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)
    registerObservers()
  }

  // MARK: PRIVATE

  private var swiftUIView = SampleView()

  private func registerObservers() {
    swiftUIView.props.incrementCount = {
      let count = self.swiftUIView.props.count + 1
      // update swiftUI view
      self.swiftUIView.props.count = count
      // notify nativescript
      self.onEvent?(["count": count])
    }
  }

  // MARK: API

  /// Receive data from NativeScript
  func updateData(data: NSDictionary) {
    if let count = data.value(forKey: "count") as? Int {
      // update swiftUI view
      swiftUIView.props.count = count
      // notify nativescript
      self.onEvent?(["count": count])
    }
  }

  /// Send data to NativeScript
  var onEvent: ((NSDictionary) -> Void)?
}

在Nativescript布局中使用Swiftui

  • app/main-page.xml
<Page
  xmlns="http://schemas.nativescript.org/tns.xsd"
  xmlns:sw="@nativescript/swift-ui"
  navigatingTo="navigatingTo"
>
  <StackLayout>
    <sw:SwiftUI swiftId="sampleView" data="{{ nativeCount }}" swiftUIEvent="{{ onEvent }}" loaded="{{ loadedSwiftUI }}" />
    <Label text="{{ 'NativeScript Label: ' + nativeCount.count }}" class="h2" />
    <Button text="NativeScript data bindings: Decrement" tap="{{ updateNativeScriptData }}" class="btn btn-primary" />
    <Button text="SwiftUI data bindings: Decrement" tap="{{ updateSwiftData }}" class="btn btn-primary" />
  </StackLayout>
</Page>
  • 冷13:
import {
  registerSwiftUI,
  UIDataDriver,
  SwiftUI,
  SwiftUIEventData,
} from "@nativescript/swift-ui";
import { 
  EventData,
  Observable,
  Page
} from "@nativescript/core";

// 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)
);

interface CountData {
  count: number;
}

export function navigatingTo(args: EventData) {
  const page = <Page>args.object;
  page.bindingContext = new DemoModel();
}

export class DemoModel extends Observable {
  swiftui: SwiftUI;
  nativeCount = {
    count: 0,
  };

  loadedSwiftUI(args) {
    this.swiftui = args.object;
  }

  onEvent(evt: SwiftUIEventData<CountData>) {
    this.set("nativeCount", { count: evt.data.count });
  }

  updateNativeScriptData() {
    this.set('nativeCount', { count: this.nativeCount.count - 1 });
  }

  updateSwiftData() {
    this.swiftui.updateData({ count: this.nativeCount.count - 1 });
  }
}

iOS屏幕

关于Valor软件:

Dmitriy Shekhovtsov(DiMa)成立于2013年,是一家平均堆栈软件开发公司,Valor已演变成全球著名的软件开发和咨询公司,超过130个人从事全面堆栈开发的130多个人,主要重点是所有事物类型,从5个TypeScript开始。大陆。

媒体联系人:sales@valor-software.com

Valor Software Logo