Swift
The same engine for iOS and macOS, with the same results as TypeScript.
On this page
The Swift SDK brings the engine to iOS 16+ and macOS 13+, with no third-party dependencies. It is a port of the TypeScript engine and gives the same results: conformance tests compare the two on every query of the eval set.
Install
dependencies: [
.package(url: "https://github.com/emojisense/emojisense-swift.git", from: "0.1.0"),
],
targets: [
.target(
name: "App",
dependencies: [.product(name: "Emojisense", package: "emojisense-swift")]
),
]Usage
import Emojisense
// 1. Load the core packs. English is always first.
let packURL = URL(string: "https://api.emojisense.com/v1/pack/0.1.0")!
let loader = PackLoader(baseURL: packURL)
let manifest = try await loader.loadManifest()
let core = try await loader.loadPacks(locales: ["en", "tr"], manifest: manifest)
var engine = try AliasEngine(core: core)
// 2. Search on every keystroke. Synchronous and fast.
let alias = engine.search("jurassic pa", options: AliasSearchOptions(locale: "en"))
var results = alias.results.map(\.searchResult)
// 3. When the device is idle, add the extension parts and rebuild the index.
let extensions = try await loader.loadPacks(
locales: ["en", "tr"], part: .ext, manifest: manifest)
engine = try AliasEngine(core: core, extensions: extensions)
// 4. Semantic layers: static shards first, then the API.
let semantic = ProviderChain([
ShardProvider(baseURL: URL(string: "https://api.emojisense.com/p/0.1.0")!),
SemanticClient(
configuration: .init(
endpoint: URL(string: "https://api.emojisense.com")!, key: "pk_live_…",
packVersion: engine.packVersion)),
])
if Fusion.shouldUseSemantic(alias),
let response = try await semantic.search("jurassic pa", options: .init(locale: "en"))
{
results = Fusion.fuse(alias: alias, semantic: response.results)
}- Debounce the semantic call, for example by 200 ms, and cancel the task when the query changes.
AliasEngineis thread-safe.SemanticClientreturnsnilwhile it pauses after anoverLimitanswer, and throwsEmojisenseError.httpStatusfor HTTP errors.ShardProviderreturnsnilon network errors, so the next provider gets the query.- Inject an
HTTPTransportto add headers, logging or a stub for tests.
Parts
| Type | What it does |
|---|---|
AliasEngine | Offline dictionary search over the packs. Runs on every keystroke. |
Normalizer | Query and label normalization, as in the pack format. |
Pack, PackLoader, Manifest | Decode the core and extension packs and verify their SHA-256. |
ShardProvider | Precomputed semantic results from static shards (layer 2). |
SemanticClient | The API in semantic mode, with an LRU cache. Over the limit it still gets the edge’s cached answers. |
Fusion | The same pinned reciprocal rank fusion as the TypeScript SDK. |
EmojiSet, Hexcode | The emojiSet option of the pickers: .native or a hosted set. imageURL(for:endpoint:) gives the image URL. No UI. |
Performance
In a release build on Apple silicon, with the English and Turkish core and extension packs, a keystroke takes 0.04 ms at the median and 0.28 ms at the 95th percentile. Building the index from decoded packs takes 0.27 s. You can also bundle the pack files in your app and decode them with try Pack(jsonData: data).