接收器 0.0.5

Receiver 0.0.5

测试已测试
Lang语言 SwiftSwift
许可证 MIT
发布最后发布2017 年 12 月
SwiftSwift 版本4.0
SPM支持 SPM

Rui Peres 维护。



Receiver 0.0.5

Receiver



codecov
Build Status
Swift 3.0
License MIT

  1. 简介
  2. 🌈输入 Receiver🌈
  3. 作为依赖项添加🚀
  4. 基本用法😎
  5. 运算符🤖
  6. 策略
  7. 定制的,在哪里?🤓
  8. 那么,我为什么会使用这个?🤷‍♀️

简介

作为自身是一位 ReactiveSwift 用户,很多时候,很难说服别人开始使用它。不管好还是坏,大多数项目/团队可能还没有准备好采用它

  1. 添加大型依赖项的内在问题。
  2. 学习曲线。
  3. 将当前代码库调整为 FRP 思维方式/方法。

尽管如此,一个宝贵的模式仍然可以用,即使没有这样一个如此棒的库,如 ReactiveSwift😖

🌈输入 Receiver🌈

Receiver 仅仅是一个意见领袖的微框架实现 观察者模式 (~120 行代码)。或者,如果您更喜欢的话,没有 F 和一个非常小的 RFRP (rP)🤔).

作为依赖项添加🚀

Carthage

如果您使用 Carthage 管理依赖项,只需将 Receiver 添加到您的 Cartfile

github "RuiAAPeres/Receiver" ~> 0.0.1

如果您使用 Carthage 构建依赖项,请确保您已经将 Receiver.framework 添加到目标 "链接框架和库" 部分,并在 Carthage 框架复制构建阶段中包含它们。

CocoaPods

如果您使用 CocoaPods 管理依赖项,只需在您的 Podfile 中添加 Receiver

pod 'Receiver', '~> 0.0.1'

基本用法😎

让我们从基础知识开始。总共 有三个方法。没错。

1. 创建接收器

let (transmitter, receiver) = Receiver<Int>.make()

一个 receiver 没有一个关联的 transmitter 无法创建(那会是什么样子?)

2. 监听事件📡

这就是您如何观察事件

receiver.listen { cheezburgers in print("Can I haz \(cheezburgers) cheezburger. 🐈") }

如预期的那样,您可以根据需要多次这样做

receiver.listen { cheezburgers in print("Can I haz \(cheezburgers) cheezburger. 🐈") }


receiver.listen { cheezburgers in print("I have \(cheezburgers) cheezburgers and you have none!")}

当事件被广播时,将调用两个处理程序。⚡️

3. 广播事件📻

这就是您发送事件的方式

transmitter.broadcast(1)

运算符🤖

Receiver 提供了一组类似于 ReactiveSwift 的运算符

  • 映射
  • 过滤
  • 带前一个
  • 跳过
  • 跳过重复项
  • 跳过空值

策略

如果您熟悉 FRP,您一定听说过 冷和热语义(即使没有也不必担心!)☺️)。代码块中的Receiver提供了三种模式,在初始化时通过make(strategy:)显式指定。默认情况下,Receiver.hot

.cold ❄️:

let (transmitter, receiver) = Receiver<Int>.make(with: .cold)
transmitter.broadcast(1)
transmitter.broadcast(2)
transmitter.broadcast(3)

receiver.listen { wave in
    // This will be called with `wave == 1`
    // This will be called with `wave == 2`
    // This will be called with `wave == 3`
    // This will be called with `wave == 4`
}

transmitter.broadcast(4)

内部,Receiver会保留之前发送的值的缓存。一旦有新的监听者接入,所有之前的值都会发送。当4被发送时,它将按预期被“监听”。

.warm(upTo: Int) 🌈:

这种策略允许你指定缓冲区的大小

let (transmitter, receiver) = Receiver<Int>.make(with: .warm(upTo: 1))
transmitter.broadcast(1)
transmitter.broadcast(2)

receiver.listen { wave in
    // This will be called with `wave == 2`
    // This will be called with `wave == 3`
}

transmitter.broadcast(3)

在这种情况下,1永远不会被调用,因为指定的限制(upTo: 1)过低,所以只保留2在缓存中。

.hot 🔥:

let (transmitter, receiver) = Receiver<Int>.make(with: .hot) // this is the default strategy
transmitter.broadcast(1)
transmitter.broadcast(2)

receiver.listen { wave in
    // This will be called with `wave == 3`
}

transmitter.broadcast(3)

在监听之前广播的内容将被丢弃。

定制的,在哪里?🤓

初始化器。🌳

代码块中的make方法遵循与ReactiveSwift中相同的处理方法,使用pipe。由于receiver只有和transmitter一起才有意义,因此它们一起创建是合乎逻辑的。

读写之间的分离。⬆️ ⬇️

许多库将读写者捆绑在同一个实体中。对于这个库的目的和使用案例,合理的做法是将这些关注点分离。这就像UITableViewUITableViewDataSource:一个供应另一个,因此将它们拆分成两个不同的实体可能更好。

那么,我为什么会使用这个?🤷‍♀️

当然,是为了让你的代码库变得非常棒。观察者模式可以在很多地方使用。在最简单的情况下,当委托不足以使用,并且存在1-to-N的关系时。

跟踪UIApplication的生命周期是这种用法的一个好例子

enum ApplicationLifecycle {
    case didFinishLaunching
    case didBecomeActive
    case didEnterBackground
}

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    private var transmitter: Receiver<ApplicationLifecycle>.Transmitter!

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        let (transmitter, receiver) = Receiver<ApplicationLifecycle>.make()
        self.transmitter = transmitter
        // Pass down the `receiver` to where it's needed (e.g. ViewModel, Controllers)

        transmitter.broadcast(.didFinishLaunching)
        return true
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        transmitter.broadcast(.didEnterBackground)
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        transmitter.broadcast(.didBecomeActive)
    }
}

类似地,同样的方法可以用于MVVM

class MyViewController: UIViewController {
    private let viewModel: MyViewModel
    private let transmitter: Receiver<UIViewControllerLifecycle>.Transmitter

    init(viewModel: MyViewModel, transmitter: Receiver<UIViewControllerLifecycle>.Transmitter) {
        self.viewModel = viewModel
        self.transmitter = transmitter
        super.init(nibName: nil, bundle: nil)
    }

    override func viewDidLoad() {
        super.viewdDidLoad()
        transmitter.broadcast(.viewDidLoad)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        transmitter.broadcast(.viewDidAppear)
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        transmitter.broadcast(.viewDidDisappear)
    }
}

好处在于UIViewController永远不需要知道receiver的存在,就像它应该的那样。

在初始化时

let (transmitter, receiver) = Receiver<UIViewControllerLifecycle>.make()
let viewModel = MyViewModel(with: receiver)
let viewController = MyViewController(viewModel: viewModel, transmitter: transmitter)