构建用户界面声明是网络社区广泛采用的东西,如今,按照这些原则构建了大型应用程序。例如,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插件
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.ts
或main.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
代码,如下所示...
iOS预览
先进的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