A client/server actor system for Swift distributed actors
APACHE-2.0 License
WebSocketActors is a client/server communications library that allows an iOS, macOS, tvOS, or watchOS app to communicate with a server on the internet using Swift's distributed actor system. It's a streamlined alternative to writing a server using Swagger/OpenAPI and then implementing your client app on top of that API. With WebSocketActors, you can make Swift function calls directly between your client and server.
This library is based on Apple's TicTacFish sample code, but adds features like:
Add the package https://github.com/samalone/websocket-actor-system
to your
Xcode project, or add:
.package(url: "https://github.com/samalone/websocket-actor-system.git", from: "1.0.0"),
to your package dependencies in your Package.swift
file. Then add:
.product(name: "WebSocketActors", package: "websocket-actor-system"),
to the target dependencies of your package target.
In your shared library, import WebSocketActors
and define your distributed
actors.
import Distributed
import WebSocketActors
extension NodeIdentity {
public static let server = NodeIdentity(id: "server")
}
extension ActorIdentity {
public static let greeter = ActorIdentity(id: "greeter", node: .server)
}
public distributed actor Greeter {
public typealias ActorSystem = WebSocketActorSystem
public distributed func greet(name: String) -> String {
return "Hello, \(name)!"
}
}
In your server code, start the server in the background and make sure the server keeps running.
func main() async throws {
let address = ServerAddress(scheme: .insecure, host: "localhost", port: 8888)
let system = WebSocketActorSystem(id: .server)
try await system.runServer(at: address)
_ = system.makeLocalActor(id: .greeter) {
Greeter(actorSystem: system)
}
while true {
try await Task.sleep(for: .seconds(1_000_000))
}
}
On the client, connect to the server and call the remote actor.
func receiveGreeting() async throws {
let address = ServerAddress(scheme: .insecure, host: "localhost", port: 8888)
let system = WebSocketActorSystem()
try await system.connectClient(to: address)
let greeter = try Greeter.resolve(id: .greeter, using: system)
let greeting = try await greeter.greet(name: "Alice")
print(greeting)
}
The documentation for WebSocketActors includes both API documentation and getting-started articles:
For a basic example of writing a client/server app using WebSocketActors, see my Monotonic project. It implements a simple iOS app that displays a counter above an "Increment" button. Clicking the increment button bumps the counters on all client apps connected to the server in real time.