Skip to main content
Version: dev

Swift

Output Layout

Swift output is one .swift file per schema, for example:

  • <swift_out>/addressbook/addressbook.swift

Type Generation

The generator creates Swift models with split model macros and stable field/case IDs. A typed union must include @ForyUnknownCase case unknown(UnknownCase) and at least one non-unknown case; unknown(UnknownCase) is only the Fory-provided forward-compatibility carrier. The marker only selects the carrier and does not add an entry to the schema case table.

When package/namespace is non-empty, namespace shaping is controlled by swift_namespace_style:

  • enum (default): nested enum namespace wrappers.
  • flatten: package-derived prefix on top-level type names (for example Demo_Foo_User).

When package/namespace is empty, no enum wrapper or flatten prefix is applied.

For non-empty package with default enum style:

public enum Addressbook {
@ForyUnion
public enum Animal {
@ForyUnknownCase
case unknown(UnknownCase)
@ForyCase(id: 0)
case dog(Addressbook.Dog)
@ForyCase(id: 1)
case cat(Addressbook.Cat)
}

@ForyStruct
public struct Person: Equatable {
@ForyField(id: 1)
public var name: String = ""
@ForyField(id: 8)
public var pet: Addressbook.Animal =
Addressbook.Animal.dog(Addressbook.Dog())
}
}

For non-empty package with flatten style:

@ForyStruct
public struct Addressbook_Person: Equatable { ... }

The CLI flag --swift_namespace_style overrides schema option swift_namespace_style when both are set.

Unions are generated as tagged Swift enums with associated payload values. Recursive unions are emitted as indirect enums. The first known union case must have a finite recursively constructible default; the compiler rejects a first-case default cycle instead of emitting a non-terminating initializer. Messages with ref/weak_ref fields are generated as final class models to preserve reference semantics. A directly stored message cycle must mark at least one cycle edge ref; otherwise the compiler rejects the schema because Swift value types cannot represent it. Fixed or tagged integer encodings inside list/map fields are emitted as Swift field type hints, for example @ListField(element: .encoding(.fixed)) or @MapField(value: .encoding(.tagged)). For non-null fixed-width integer list elements, Swift classifies the field as the corresponding Fory primitive packed-array type; fixed-width integer sets remain Fory sets.

Module Installation

Each schema includes a ForyModule owner with transitive import installation:

public enum ForyModule {
public static func install(_ fory: Fory) throws {
try ComplexPb.ForyModule.install(fory)
try fory.register(Addressbook.Person.self, id: 100)
try fory.register(Addressbook.Animal.self, id: 106)
}
}

With non-empty package and flatten style, the helper is prefixed too (for example Addressbook_ForyModule).

For schemas without explicit [id=...], installation uses computed numeric IDs. If option enable_auto_type_id = false; is set, generated code uses name-based registration APIs.