Plugins
SwiftUI
@nativescript/swift-ui β
Use SwiftUI with NativeScript.
Contents β
- @nativescript/swift-ui
Installation β
npm install @nativescript/swift-ui
Note
you will need to target iOS 13 at a minimum.
For example, you can add this line to your App_Resources/iOS/build.xcconfig
:
IPHONEOS_DEPLOYMENT_TARGET = 13.0
Note
If you would like to use NativeScriptView
inside SwiftUI, you should target 14.0 minimum.
Usage β
SwiftUI Source Files Example
1. Create your SwiftUI view β
This can be any SwiftUI view you'd like to create.
importSwiftUI
structSampleView: View {
var body: some View {
VStack {
Text("Hello World")
.padding()
}
}
}
2. Create your SwiftUI view Provider β
This will prepare your SwiftUI for two-way data bindings to NativeScript and follows the plugins' SwiftUIProvider
protocol to standardize all SwiftUI bindings.
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. Register your SwiftUI with an identifier and use it in markup β
This can be done in the bootstrap file (often app.ts
or main.ts
) or even the view component that needs it.
Core β
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
declareconstSampleViewProvider:any
registerSwiftUI(
'sampleView',
(view) =>newUIDataDriver(SampleViewProvider.alloc().init(), view),
)
registerSwiftUI(
'barChart',
(view) =>newUIDataDriver(BarChartProvider.alloc().init(), view),
)
Then insert it in any layout as follows:
<Pagexmlns="http://schemas.nativescript.org/tns.xsd"navigatingTo="navigatingTo"class="page"xmlns:sw="@nativescript/swift-ui">
<StackLayout>
<sw:SwiftUIswiftId="sampleView"height="150" />
</StackLayout>
</Page>
Generate Types β
To generate types for your SwiftUI code, run
ns typings ios
.Locate the
objc!nsswiftsupport.d.ts
file intypings/x86_64
and reference it in thereferences.d.ts
.
SwiftUI with Angular β
Register SwiftUI follows:
import { registerElement } from'@nativescript/angular'
import { SwiftUI } from'@nativescript/swift-ui'
registerElement('SwiftUI', () => SwiftUI)
registerSwiftUI(
'sampleView',
(view) =>newUIDataDriver(SampleViewProvider.alloc().init(), view),
)
registerSwiftUI(
'barChart',
(view) =>newUIDataDriver(BarChartProvider.alloc().init(), view),
)
It can now be used within any Angular component, eg:
<StackLayoutclass="p-20">
<SwiftUIswiftId="sampleView"height="150"></SwiftUI>
</StackLayout>
SwiftUI with Vue β
Register SwiftUI follows:
registerElement('SwiftUIView', () =>require('@nativescript/swift-ui').SwiftUI)
registerSwiftUI(
'sampleView',
(view) =>newUIDataDriver(SampleViewProvider.alloc().init(), view),
)
registerSwiftUI(
'barChart',
(view) =>newUIDataDriver(BarChartProvider.alloc().init(), view),
)
Then use it in markup as follows:
<StackLayout>
<SwiftUIViewswiftId="sampleView"height="200" />
<SwiftUIViewheight="500"swiftId="barChart"margin="30" />
</StackLayout>
SwiftUI with React β
Register SwiftUI follows:
registerSwiftUI(
'sampleView',
(view) =>newUIDataDriver(SampleViewProvider.alloc().init(), view),
)
registerSwiftUI(
'barChart',
(view) =>newUIDataDriver(BarChartProvider.alloc().init(), view),
)
interfaceSwiftUIViewAttributesextendsViewAttributes {
swiftId:string
}
declare global {
moduleJSX {
interfaceIntrinsicElements {
swiftUIView:NativeScriptProps<SwiftUIViewAttributes, SwiftUI>
}
}
}
registerElement('swiftUIView', () =>require('@nativescript/swift-ui').SwiftUI)
Then use it in markup as follows:
<stackLayout>
<swiftUIViewswiftId="sampleView"height="200" />
<swiftUIViewheight="500"swiftId="barChart"margin="30" />
</stackLayout>
Open Multiple Scenes β
When using a SwiftUI App Lifecycle setup for your NativeScript app, the default with visionOS development, you can enable multiple scenes in your Info.plist
with the following:
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationPreferredDefaultSceneSessionRole</key>
<string>UIWindowSceneSessionRoleApplication</string>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict/>
</dict>
You can now use WindowManager
(for use with standard Windows) or XR
(for use with immersive spaces) to interact with multiple scenes, for example:
@main
structNativeScriptApp: App {
@Stateprivatevar immersionStyle: ImmersionStyle = .mixed
var body: some Scene {
NativeScriptMainWindow()
WindowGroup(id: "NeatView") {
NeatView()
}
.windowStyle(.plain)
ImmersiveSpace(id: "NeatImmersive") {
NeatImmersive()
}
.immersionStyle(selection: $immersionStyle, in: .mixed, .full)
}
}
You could open the WindowGroup
with:
import { WindowManager } from"@nativescript/swift-ui";
WindowManager.getWindow("NeatView").open();
});
And you could open the ImmersiveSpace
with:
import { XR } from'@nativescript/swift-ui'
XR.requestSession('NeatImmersive')
You could update either scene with:
import { WindowManager } from'@nativescript/swift-ui'
// Option A: inline
WindowManager.getWindow('NeatView').update({
title: 'Updated Title',
})
// Option B: reference
constneatView= 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',
})
Passing contextual data to scenes β
You can use the onReceive
modifier in SwiftUI to handle any data passed to your windows.
For example, anytime WindowManager.getWindow("Window_ID").update(...)
is called, a Notification is dispatched which can be picked up for data to be handled:
structNeatView: View {
@Statevar 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!
})
}
}
Closing windows β
WindowManager.getWindow("NeatView").close()
for a Window which is already open will close it.
XR.endSession()
for an Immersive Space which is already open will close it.
Use NativeScriptView inside SwiftUI β
You can also use NativeScript view layouts and components inside SwiftUI when targeting iOS 14.0 minimum.
Add this line to your App_Resources/iOS/build.xcconfig
:
IPHONEOS_DEPLOYMENT_TARGET = 14.0
You can now register as many NativeScript views by an id for usage:
import { SwiftUIManager } from'@nativescript/swift-ui'
SwiftUIManager.registerNativeScriptViews({
Video: SceneVideoComponent,
})
This will allow SceneVideoComponent
, a NativeScript view component, to be used inside any SwiftUI component:
structContentView: View {
var body: some View {
ZStack {
NativeScriptView(id: "Video")
}
}
}
Credits β
- WindowManager and XR APIs were established with the Callstack team. Shoutout to: Oskar KwaΕniewski.
NativeScript is proudly supported by Valor Software as an official partner. We are proud to offer guidance, consulting, and development assistance in all things NativeScript.
License β
MIT
- Previous
- Social Share
- Next
- Tailwind CSS
- Contents
- Installation
- Usage
- Open Multiple Scenes
- Use NativeScriptView inside SwiftUI
- Credits
- License
Contributors
Last updated: