There are 3 steps in this series of articles,
- Step 1: Interactive html file and SwiftUI View
- Step 2: Embed Javascript files
- Step 3: Build TCA reducer
Architecture
The html file and javascript files are encapsulated in a SwiftUI View, JavascriptWKCoordinatorSwiftUIView. It uses notifications to communicate with others.
- call javascript from Swift
- post message from javascript
JavascriptWKCoordinatorSwiftUIView
ExampleSwiftUIView
First, let's see if everything works properly in the Xcode Preview.
We can call the same javascript function from either the SwiftUI View or the html file.
Please refer to step 2 for the html file and javascript files.
Here is the ExampleSwiftUIView.
TCA Reducer
The key task is to actively listen to specific notification. This is by implementing the AsyncStream<Notification>.
TCA provides some sample code for the AsyncStream.
We will make a NotificationReducer which would listen to specific notification. And then write the unit test.
- NotificationReducer
- unit test
ExampleSwiftUIView with TCA
Now we could integrate TCA reducer into the ExampleSwiftUIView.
The key points here is,
- Start the listening task in the view modifier .task{}
.task {
await viewStore.send(.listening).finish()
}
- Separate any view state change with JavascriptWKCoordinatorSwiftUIView.
The final code is here.
Reference
- AsyncThrowingStream and AsyncStream explained with code examples
- TCA provides some sample code for the AsyncStream. This application demonstrates how to handle long-living effects, for example notifications from Notification Center, and how to tie an effect’s lifetime to the lifetime of the view.