Skip to main content
Skip table of contents

Writing a Greeter Client in Swift

This page presents a step-by-step guide to writing the client-side of our Swift Greeter application.

This client creates a proxy to a remote object that implements the Greeter interface and invokes the greet operation on this object.

You can find the complete source code for this example in the ice-demos repository.

Compile Slice File with Slice Compiler

To write a Swift application with Ice, first configure SwiftPM to compile the Slice definitions. The Ice package contains a plugin for this purpose, CompileSwift, which can be added to the executableTarget in Package.swift.

SWIFT
.executableTarget(
    name: "Client",
    dependencies: [.product(name: "Ice", package: "ice-swift-nightly")],
    plugins: [.plugin(name: "CompileSlice", package: "ice-swift-nightly")]
),

The CompileSwift plugin compiles Greeter.ice into Greeter.swift and adds it as source file of the Server target. The generated code provides the APIs that we’ll call in our client code, so it’s an essential step of the development process.

Client Implementation

To get started we first need to import a few dependencies.

SWIFT
import Foundation
import Ice
  • Foundation - Used to obtain the username.

  • Ice - For accessing the Ice runtime

Next is the client logic, which can be broken down into four pieces:

1. Create a Communicator

First, we create a Communicator with Ice.initialize:

SWIFT
var args = CommandLine.arguments
let communicator = try Ice.initialize(&args)

defer {
    communicator.destroy()
}

The communicator is the main entry point into the Ice runtime. Its responsibilities include establishing connections to servers, caching these connections, and managing configuration properties. We also need a communicator to create a proxy (see next step).

Our client, like most Ice applications, creates a single communicator.

It is important to properly clean up the communicator when done, which we do with the defer block that calls destroy().

2. Create a Greeter Proxy

Next, we need a way to call on a remote Greeter object. In Ice, this is done with proxies. Proxies are local constructs that represent remote Ice objects and provide methods to call operations on those objects.

We create a Greeter proxy by constructing an instance of the GreeterPrx class generated by the Slice compiler:

SWIFT
let greeter = try makeProxy(
    communicator: communicator, proxyString: "greeter:tcp -h localhost -p 4061",
    type: GreeterPrx.self)

The makeProxy function accepts our communicator and a “stringified proxy” with the address of the remote Ice object. Here, our stringified proxy says that the target Ice object is named “greeter” and can be reached via tcp on localhost on port 4061.

The name of the interface (Greeter) and the identity of the Ice object (greeter) are independent. The Ice objects hosted in the server could just as easily have identities like santa, bugsBunny, etc.

3. Make an Invocation

The third step is to call greet on the remote Ice object using our proxy and to print the greeting:

SWIFT
let greeting = try await greeter.greet(NSUserName())
print(greeting)

The greet method does all the heavy lifting for us: the proxy creates a request with the username, the communicator establishes a connection to localhost:4061, and the request is sent over it. When a response is received, the proxy unmarshals its payload and returns a string (the greeting).

Using async/await for this invocation offers several advantages:

  • The calling thread can continue doing other work while greet waits for I/O.

  • The await keyword signals to the reader that greet is a remote operation and may take time to complete.

4. Cleanup

When the main function exits, the defer statement destroys the communicator.

Run the Client

To run the client, execute the following command (the executable will be compiled if necessary):

CODE
swift run Client

This client won’t work unless you’ve also launched a Greeter server.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.