yswift
Swift version of yjs.
y-uniffi is a great yjs Swift implementation though,
I have created a completely Swift reimplementation of yjs, as y-uniffi dose not yet have a nested Map, UndoManager, etc. implementation.
Important
Now this library is based on yjs and implemented in Swift for a personal use and is not intended to be fully compatible with yjs.
Install
dependencies: [
.package(url: "https://github.com/ObuchiYuki/yswift.git", branch: "1.0.0"),
]
Features
Objects
YArray
Swift implementation of YArray
final public class YArray<Element: YElement>
example
// init with array literal
let intArray: YArray<Int> = [1, 2]
print(intArray) // [1, 2]
// index access
print(intArray[1]) // 2
// append Element
intArray.append(3)
print(intArray) // [1, 2, 3]
// append Sequence
intArray.append(contentsOf: [4, 5])
print(intArray) // [1, 2, 3, 4, 5]
// range access
print(intArray[2...]) // [3, 4, 5]
// use as Sequence
for i in intArray {
print(i) // 1, 2 ...
}
// YArray with YMap type
let mapArray: YArray<YMap<Int>> = [
["Apple": 160]
]
mapArray.append(["Banana": 240])
YMap
Swift implementation of YMap
final public class YMap<Value: YElement>
example
// init with dictionary literal
let intMap: YMap<Int> = [
"Apple": 160
]
// subscript access
intMap["Banana"] = 240
print(intMap["Apple"]) // 160
// nested map
let arrayMap: YMap<YArray<Int>> [
"Alice": [12, 24],
"Bob": [24, 64, 75]
]
YObject
Binding to classes based on YMap
open class YObject: YOpaqueObject
example
class Person: YObject {
// Syncronized property
@Property var name: String = ""
// nested proeprty
@WProperty var children: YArray<Person> = []
required init() {
super.init()
self.register(_name, "name")
self.register(_children, "children")
}
convenience init(name: String) {
self.init()
self.name = name
}
}
let person = Person(name: "Alice")
// can use as Combine Publisher
person.$name
.sink{ print("name is \($0)") }.store(in: &bag)
person.$children
.sink{ print("children is \($0)") }.store(in: &bag)
// update to property to sync
person.name = "Bob"
// update nested type to sync
person.children.append(Person(name: "Bobson"))
YRefrence
Store a reference to an object.
class Layer: YObject {
@Property var parent: YReference<Layer>? = nil
@WProperty var children: YArray<Person> = []
func addChild(_ child: Layer) {
self.children.append(child)
// make Reference
child.parent = YReference(self)
}
...
}
let root = Layer("root")
root.addChild(Layer("child0"))
// copy dosen't change a reference.
let copiedRoot = root.copy()
// fail
assert(copiedRoot.children[0].parent.value === copiedRoot)
// smart copy changes a reference.
let smartCopiedRoot = root.smartCopy()
// success
assert(smartCopiedRoot.children[0].parent.value === smartCopiedRoot)
YElement
YElement
is a protocol that is inherited by values that can be YArray
, YMap
values, and YObject
properties.
public protocol YElement {
/// Make opaque data concrete.
static func fromOpaque(_ opaque: Any?) -> Self
/// Make concrete data opaque.
func toOpaque() -> Any?
}
You can use YCodable
to turn a Codable
value into a YElement
, or YRawRepresentable
to turn an enum into a YElement
.
struct Point: YCodable {
var x: CGFloat
var y: CGFloat
}
let array = YArray<Point>()
array.append(Point(x: 1, y: 3))
enum LayerKind: String, YRawRepresentable {
case rect
case text
case path
}
let map = YMap<LayerKind>()
map["rect"] = .rect
map["text"] = .text
Or you can create a YElement
by defining your own encoding and decoding.
enum Delta<T: YElement>: YElement {
case by(T)
case to(T)
public func toOpaque() -> Any? {
switch self {
case .by(let value): return ["by": value.toOpaque()]
case .to(let value): return ["to": value.toOpaque()]
}
}
public static func fromOpaque(_ opaque: Any?) -> Self {
let (key, value) = (opaque as! [String: Any?]).first
if (key == "by") { return .by(T.fromOpaque(value)) }
if (key == "to") { return .to(T.fromOpaque(value)) }
fatalError("Unexpected case.")
}
}
yswift
Swift version of yjs.
y-uniffi is a great yjs Swift implementation though, I have created a completely Swift reimplementation of yjs, as y-uniffi dose not yet have a nested Map, UndoManager, etc. implementation.
Important
Now this library is based on yjs and implemented in Swift for a personal use and is not intended to be fully compatible with yjs.
Install
Features
Objects
YArray
Swift implementation of YArray
example
YMap
Swift implementation of YMap
example
YObject
Binding to classes based on YMap
example
YRefrence
Store a reference to an object.
YElement
YElement
is a protocol that is inherited by values that can beYArray
,YMap
values, andYObject
properties.You can use
YCodable
to turn aCodable
value into aYElement
, orYRawRepresentable
to turn an enum into aYElement
.Or you can create a
YElement
by defining your own encoding and decoding.