| Use in Swift {#flatbuffers_guide_use_swift} | |
| ========= | |
| ## Before you get started | |
| Before diving into the FlatBuffers usage in Swift, it should be noted that | |
| the [Tutorial](../tutorial.md) page has a complete guide | |
| to general FlatBuffers usage in all of the supported languages (including Swift). | |
| This page is designed to cover the nuances of FlatBuffers usage, specific to | |
| Swift. | |
| You should also have read the [Building](../building.md) | |
| documentation to build `flatc` and should be familiar with | |
| [Using the schema compiler](../flatc.md) and | |
| [Writing a schema](../schema.md). | |
| ## FlatBuffers Swift library code location | |
| The code for the FlatBuffers Swift library can be found at | |
| `flatbuffers/swift`. You can browse the library code on the [FlatBuffers | |
| GitHub page](https://github.com/google/flatbuffers/tree/master/swift). | |
| ## Testing the FlatBuffers Swift library | |
| The code to test the Swift library can be found at `flatbuffers/tests/swift/tests`. | |
| The test code itself is located in [flatbuffers/tests/swift/tests](https://github.com/google/flatbuffers/blob/master/tests/swift/tests). | |
| To run the tests, use the [SwiftTest.sh](https://github.com/google/flatbuffers/blob/master/tests/swift/tests/SwiftTest.sh) shell script. | |
| *Note: The shell script requires [Swift](https://swift.org) to | |
| be installed.* | |
| ## Using the FlatBuffers Swift library | |
| *Note: See [Tutorial](../tutorial.md) for a more in-depth | |
| example of how to use FlatBuffers in Swift.* | |
| FlatBuffers supports reading and writing binary FlatBuffers in Swift. | |
| To use FlatBuffers in your own code, first generate Swift structs from your | |
| schema with the `--swift` option to `flatc`. Then include FlatBuffers using `SPM` in | |
| by adding the path to `FlatBuffers/swift` into it. The generated code should also be | |
| added to xcode or the path of the package you will be using. Note: sometimes xcode cant | |
| and wont see the generated files, so it's better that you copy them to xcode. | |
| For example, here is how you would read a FlatBuffer binary file in Swift: First, | |
| include the library and copy thegenerated code. Then read a FlatBuffer binary file or | |
| a data object from the server, which you can pass into the `GetRootAsMonster` function. | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift} | |
| import FlatBuffers | |
| typealias Monster1 = MyGame.Sample.Monster | |
| typealias Vec3 = MyGame.Sample.Vec3 | |
| let path = FileManager.default.currentDirectoryPath | |
| let url = URL(fileURLWithPath: path, isDirectory: true).appendingPathComponent("monsterdata_test").appendingPathExtension("mon") | |
| guard let data = try? Data(contentsOf: url) else { return } | |
| let monster: Monster = try! getCheckedRoot(byteBuffer: &byteBuffer) | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| Now you can access values like this: | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift} | |
| let hp = monster.hp | |
| let pos = monster.pos // uses native swift structs | |
| let pos = monster.mutablePos // uses flatbuffers structs | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated. | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift} | |
| var byteBuffer = ByteBuffer(bytes: data) | |
| // Get an accessor to the root object inside the buffer. | |
| let monster: Monster = try! getCheckedRoot(byteBuffer: &byteBuffer) | |
| // let monster: Monster = getRoot(byteBuffer: &byteBuffer) | |
| if !monster.mutate(hp: 10) { | |
| fatalError("couldn't mutate") | |
| } | |
| // mutate a struct field using flatbuffers struct | |
| // DONT use monster.pos to mutate since swift copy on write | |
| // will not mutate the value in the buffer | |
| let vec = monster.mutablePos.mutate(z: 4) | |
| // This mutation will fail because the mana field is not available in | |
| // the buffer. It should be set when creating the buffer. | |
| if !monster.mutate(mana: 20) { | |
| fatalError("couldn't mutate") | |
| } | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer. | |
| <br> |