跳到主要内容
版本:dev

Shared and Circular References

Swift reference tracking is controlled by ForyConfig.trackRef.

Enable Reference Tracking

let fory = Fory(xlang: true, trackRef: true, compatible: false)

When enabled, reference-trackable types preserve identity and cycles.

Shared Reference Example

import Fory

@ForyObject
final class Animal {
var name: String = ""

required init() {}

init(name: String) {
self.name = name
}
}

@ForyObject
final class AnimalPair {
var first: Animal? = nil
var second: Animal? = nil

required init() {}

init(first: Animal? = nil, second: Animal? = nil) {
self.first = first
self.second = second
}
}

let fory = Fory(xlang: true, trackRef: true)
fory.register(Animal.self, id: 200)
fory.register(AnimalPair.self, id: 201)

let shared = Animal(name: "cat")
let input = AnimalPair(first: shared, second: shared)

let data = try fory.serialize(input)
let decoded: AnimalPair = try fory.deserialize(data)

assert(decoded.first === decoded.second)

Circular Reference Example (Use weak)

trackRef preserves the reference graph, but it does not change ARC ownership. Use weak on at least one edge in a cycle to avoid leaks.

import Fory

@ForyObject
final class Node {
var value: Int32 = 0
weak var next: Node? = nil

required init() {}

init(value: Int32, next: Node? = nil) {
self.value = value
self.next = next
}
}

let fory = Fory(xlang: true, trackRef: true)
fory.register(Node.self, id: 300)

let node = Node(value: 7)
node.next = node

let data = try fory.serialize(node)
let decoded: Node = try fory.deserialize(data)

assert(decoded.next === decoded)

Notes

  • Value types (struct, primitive values) do not carry identity semantics
  • trackRef controls serialization graph identity, not ARC memory ownership
  • Use trackRef=false for purely value-based payloads to reduce overhead