ZDCSyncable 2.2.4

ZDCSyncable 2.2.4

Robbie Hanson 维护。



  • 作者:
  • Robbie Hanson

ZDCSyncable

为纯 Swift 中的结构体和类提供撤消、重做和合并功能。

作者:ZeroDark.cloud:一个安全同步和消息框架,基于区块链和 AWS 构建您的应用程序。

 

撤消和重做

示例 #1

import ZDCSyncable

struct Person: ZDCSyncable { // Just add ZDCSyncable protocol

  @Syncable var name: String // Then add @Syncable property wrapper.
  @Syncable var age: Int = 1 // And that's it!
}

// And now you get undo & redo support

let person = Person(name = "alice")
// ^ starting point

person.name = "bob"
person.age = 2
		
let changeset = person.changeset() // changes since starting point
do {
  let redo = try person.undo(changeset!) // revert to starting point

  // Current state:
  // person.name == "alice"
  // person.age == 1

  let _ = try person.undo(redo) // redo == (undo an undo)

  // Current state:
  // person.name == "bob"
  // person.age == 2
			
} catch _ {}

如果您想使用类而不是结构体,这也是支持的

示例 #2

import ZDCSyncable

class Animal: ZDCRecord { // <- Just extend ZDCRecord

  @Syncable var species: String // And add @Syncable property wrapper.
  @Syncable var age: Int
}

 

@Syncable 属性包装器适用于原始数据类型。

该框架还提供了一些额外的解决方案来替换集合类型

  • ZDCArray
  • ZDCDictionary
  • ZDCOrderedDictionary
  • ZDCSet
  • ZDCOrderedSet

这些集合类型与原生的 Swift API 类似。并且它们都是作为结构体实现的,因此您会得到熟悉的价值语义。

示例 #3

import ZDCSyncable

struct Television: ZDCSyncable { // Add ZDCSyncable protocol

  @Syncable var brand: String // Add @Syncable property wrapper.
  
  // Or use syncable collection class:
  var specs = ZDCDictionary<String, String>()
  
  // ZDCDictionary has almost the exact same API as Swift's Dictionary.
  // And ZDCDictionary is a struct, so you get the same value semantics.
}

var tv = Television(brand: "Samsung")
tv.specs["size"] = "30"
tv.clearChangeTracking() // set starting point
		
tv.brand = "Sony"
tv.specs["size"] = "40"
tv.specs["widescreen"] = "true"
		
let changeset = tv.changeset() // changes since starting point
do {
  let redo = try tv.undo(changeset!) // revert to starting point
  
  // Current state:
  // tv.brand == "Samsung"
  // tv.specs["size"] == "30"
  // tv.specs["widescreen"] = nil

  let _ = try tv.undo(redo) // redo == (undo an undo)

  // Current state:
  // tv.brand == "Sony"
  // tv.specs["size"] == "40"
  // tv.specs["widescreen"] = "true"
			
} catch _ {}

合并

您还可以合并更改! (例如从云端)

var localTV = Television(brand: "Samsung")
localTV.specs["size"] = "30"
localTV.clearChangeTracking() // set starting point
		
var cloudTV = localTV // Television is a struct
var changesets: [ZDCChangeset] = []
	
// local modifications

localTV.specs["size"] = "30.5"
localTV.specs["widescreen"] = "yes"
	
changesets.append(localTV.changeset() ?? ZDCChangeset())
// ^ pending local changes (not yet pushed to cloud)

// cloud modifications

cloudTV.specs["hdmi inputs"] = "2"

// Now merge cloud version into local.
// Automatically take into account our pending local changes.

do {
  try localTV.merge(cloudVersion: cloudTV, pendingChangesets: changesets)
	
  // Merged state:
  // localTV.brand == "Samsung"
  // localTV.specs["size"] == "30.5"
  // localTV.specs["widescreen"] == "true"
  // localTV.specs["hdmi inputs"] = "2"
} catch _ {}

 

入门指南

ZDCSyncable 可通过 CocoaPods 获取。

CocoaPods

请将以下内容添加到您的 Podfile 中

pod 'ZDCSyncable'

然后像往常一样运行 pod install。然后您可以通过以下方式导入它

// Swift
import ZDCSyncable

 

推动因素

发生了合并冲突。如果您之前使用过 git,那么您会很熟悉这种情况。解决合并冲突需要知道改动了什么。这与数据模型也是一样的。

考虑一个简单的例子——同步一个朴实无华的字典。假设我们得知了一个冲突,但我们只知道以下这些

{
  "local version": {
    "size": "30.5",
    "widescreen": "true"
  },
  "remote version": {
    "size": "30",
    "hdmi inputs": "2"
  }
}

合并后的值应该是什么?

如果我们只使用上述信息,我们无法做出明智的决定

  • 是谁更改了 size 属性?本地?远程?两者都更改了?谁胜出?
  • 远程是否删除了 widescreen?还是本地添加了它?
  • 远程是否添加了 hdmi inputs?还是本地删除了它?

ZDCSyncable 通过提供您所需的信息来帮助您解决合并冲突。它是通过跟踪更改并提供一个更改集来做到这一点的。

{
  "local version": {
    "size": "30.5",
    "widescreen": "true"
  },
  "remote version": {
    "size": "30",
    "hdmi inputs": "2"
  },
  "local changeset": {
    "size": {
      "type": "changed",
      "previous": "30"
    },
    "widescreen": {
      "type": "added"
    }
  }
}

有了这些信息,合并就变得显而易见了

  • size 属性是本地更改的,远程没有更改。本地胜出
  • widescreen 属性是本地添加的
  • hdmi inputs 属性是由远程添加的

ZDCSyncable 项目为您提供了所需的工具

  • 来跟踪数据模型的更改
  • 在更改上传的过程中存储这些更改集
  • 通过考虑本地更改集,正确地合并来自云端的更改

说实话,编写这些代码并不困难。这并不是火箭科学。但它确实需要进行大量的单元测试,以确保所有细微的边缘情况都正确无误。这意味着您可以选择自己编写所有的单元测试,或者使用一个已经由社区测试过的开源版本。(然后您可以用额外的时间使您的应用变得很棒。)