Sync

0.1.0

Real-time Apps the SwiftUI way
nerdsupremacist/Sync

What's New

2022-02-20T21:45:23Z

Sync

Swift Package Manager Twitter: @nerdsupremacist

Sync

Sync is a proof of concept for expanding on the Magic of ObservableObject, and making it work over the network. This let's you create real-time Apps in which your Observable Objects are in sync across multiple devices. This has a lot of applications just as:

  • IoT Apps
  • Multi-Player Mini Games
  • etc.

As of right now Sync works out of the box using WebSockets, however, it's not limited to web sockets and it allows for multiple kinds of connections. Some possible connections could be:

  • Bluetooth
  • Multi-Peer
  • MQTT
  • etc.

The sky is the limit!

Warning: This is only a proof of concept that I'm using for exeprimentation. I assume there's lots and lots of bugs in there...

Installation

Swift Package Manager

You can install Sync via Swift Package Manager by adding the following line to your Package.swift:

import PackageDescription

let package = Package(
    [...]
    dependencies: [
        .package(url: "https://github.com/nerdsupremacist/Sync.git", from: "0.1.0")
    ]
)

Usage

If you have ever used Observable Object, then Sync will be extremely easy to use. For this example we will create an app with a Switch that everyone can flip on or off as they like. We will build this using SwiftUI, WebSockets and a Vapor Server.

Sync

For this we will need a few additional packages:

Let's start by building our shared ViewModel. This is easy, instead of using ObservableObject we use SyncedObject. And instead of Published we use Synced:

class ViewModel: SyncedObject {
    @Synced
    var toggle: Bool = false

    init() { }
}

This ViewModel needs to be both on your App codebase as well as on the Server codebase. I recommend putting it in a shared Swift Package, if you're feeling fancy.

Next stop is to create our server. In this example every client will be using the exact same ViewModel. So we're creating a Vapor application, and using syncObjectOverWebSocket to provide the object:

import Vapor
import SyncWebSocketVapor

let app = Application(try .detect())

let viewModel = ViewModel()
app.syncObjectOverWebSocket("view_model") { _ in
    return viewModel
}

try app.run()

For our SwiftUI App, we need to use two things:

  • @SyncedObservedObject: Like ObservedObject, but for Synced Objects. It's a property wrapper that will dynamically tell SwiftUI when to update the UI
  • Sync: A little wrapper view to start the remote session

Our actual view then uses SyncedObservedObject with our ViewModel

struct ContentView: View {
    @SyncedObservedObject
    var viewModel: ViewModel

    var body: some View {
        Toggle("A toggle", isOn: $viewModel.toggle)
            .animation(.easeIn, value: viewModel.toggle)
            .padding(64)
    }
}

And in order to display it we use Sync, and pass along the Web Socket Connection:

struct RootView: View {
    var body: some View {
        Sync(ViewModel.self, using: WebSocketClientConnection(url: url)) { viewModel in
            ContentView(viewModel: viewModel)
        }
    }
}

Contributions

Contributions are welcome and encouraged!

License

Sync is available under the MIT license. See the LICENSE file for more info.

Description

  • Swift Tools 5.5.0
View More Packages from this Author

Dependencies

  • None
Last updated: Wed Feb 28 2024 15:55:43 GMT-1000 (Hawaii-Aleutian Standard Time)