SGSwiftyBind

一种轻量级的基于事件的编程方法

Build Status codecov Swift 4.0 CocoaPods Carthage DUB platform standard-readme compliant

目录

背景

在开发使用诸如 Model-View-Viewmodel 架构的应用程序时,当需要知道对象中的值何时更改,或者仅仅是想要拥有一个基于通知的 API 时,我发现使用像 NotificationCenter 这样的 API 很难编写好的单元测试来验证执行是否发生。此外,使用这些现有的 API 会助长不使用单向数据流的不良实践。

安装

CocoaPods

您可以使用 CocoaPods,通过将其添加到您的 Podfile 文件中来安装 SGSwiftyBind

platform :ios, '9.0'
use_frameworks

target 'MyApp' do
    pod 'SGSwiftyBind'
end

Carthage

您可以使用 Carthage,通过将其添加到您的 Cartfile 文件中来安装 SGSwiftyBind

github "eman6576/SGSwiftyBind"

Swift Package Manager

您可以使用 Swift Package Manager,通过将正确的描述添加到您的 Package.swift 文件中来安装 SGSwiftyBind

import PackageDescription

let package = Package(
    name: "YOUR_PROJECT_NAME",
    dependencies: [
        .package(url: "https://github.com/eman6576/SGSwiftyBind.git", from: "1.0.0")
    ],
    targets: [
        .target(
            name: "YOUR_TARGET_NAME",
            dependencies: [
                "SGSwiftyBind"
            ])
    ]
)

用法

注意:此仓库包含一个 examples 目录,其中包含关于如何使用此库的不同示例。我们建议您尝试这些示例。同时,请查看单元测试以了解库的实际应用。

初始化

要访问可用的数据类型,请像这样将 SGSwiftyBind 导入到您的项目中

import SGSwiftyBind

功能

SGSwiftyBind 使用泛型来存储不同的数据类型

let intBind: SGSwiftyBind<Int> = SGSwiftyBind(1)
let doubleBind: SGSwiftyBind<Double> = SGSwiftyBind(1.2)
let stringBind: SGSwiftyBind<String> = SGSwiftyBind("Hello World")

您甚至可以使用您自己的自定义类型

protocol Animal {
    var age: Int { get }

    init(age: Int)

    func makeSound()

    func increaseAge()
}

struct Dog: Animal {
    var age: Int

    init(age: Int) {
        self.age = age
    }

    func makeSound() {
        print("Bark")
    }

    func increaseAge() {
        age += 1
    }
}

let dog = Dog(age: 3)
let animalBind: SGSwiftyBind<Animal> = SGSwiftyBind(dog)

使用 SGSwiftyBind 的一个很好的用例是了解变量何时更改或某些事件发生。让我们修改我们的 Animal 协议以使用 SGSwiftyBind

protocol Animal {
    var age: SGSwiftyBindInterface<Int> { get }

    init(age: Int)

    func makeSound()

    func increaseAge()
}

struct Dog: Animal {
    var age: SGSwiftyBindInterface<Int> {
        return ageBind.interface
    }

    private let ageBind: SGSwiftyBind<Int>

    init(age: Int) {
        ageBind = SGSwiftyBind(age)
    }

    func makeSound() {
        print("Bark")
    }

    func increaseAge() {
        ageBind.value += 1
    }
}

我们修改了我们的 Animal 协议,使其在 age 属性上具有绑定器接口。我们的 Dog 类将需要更新其 age 属性以返回绑定器接口,并添加了一个名为 ageBind 的私有绑定器,类型为 SGSwiftyBind<Int>。现在让我们使用我们的 Dog 对象

let dog = Dog(age: 3)

dog.age.bind({ (newAge) in
    print("This is the dog's new age: \(newAge)")
}, for: self)

dog.makeSound()
dog.increaseAge()

在示例中,我们分配了一个 Dog 实例。然后,我们在 age 属性上注册一个绑定器,以便在值更改时,我们可以获取新值并对其进行一些操作。在我们的例子中,我们将值打印到控制台。

Dog 实例上的 age 属性的类型是 SGSwiftyBindInterface<Int> 而不是 SGSwiftyBind<Int>。这背后的想法是为了外部不能改变 ageBind 的状态。这是一个例子

let currentAge = dog.age.value // We can retrieve the current value of age
dog.age.value = currentAge     // The complier would give us an error stating that `age.value` is a get-only property

一旦我们完成了在 Dog 实例上使用绑定器,我们应该执行一些清理并像这样移除它

dog.age.unbind(for: self)

我们还可以获取已注册特定绑定器的当前观察者数量

let observerCount = dog.age.observerCount

贡献

请参阅贡献文件

接受 PR。

小提示:如果编辑 Readme,请遵守 standard-readme 规范。

维护者

Manny Guerrero Twitter Follow GitHub followers

许可

MIT © Manny Guerrero.