5

我已经多次阅读文档并需要澄清......

鉴于以下片段:

let signal: Signal<Value,Error>

//call this observer y
signal.take(first: 1).observeValues{ (value) in
  //intended strong capture on self. this is the only one that retains self so if this observer is triggered and completes, self should dealloc
 self.doSomethingElse(value) //trivial call, no async or thread hopping
}

//call this observer x
signal.take(duringLifetimeOf: self).observeValues{ [unowned self] (value) in //is this safe or better to use weak and guard against it? 
   self.doSomeProcess(value) //trivial call, no async or thread hopping
}

Ifsignal被触发并通知其观察者value event

1)y之前会通知观察者x(假设因为它在队列中更早地被第一次观察到)

2)由于y在处理完值后会完成,所以self应该在之后释放

问题:

哪些事件将x收到(按顺序):

  • 价值和完成度?是否保证在处理价值事件时 self 仍然活着?

  • 只完成?我怀疑是这种情况,但如果是这样,请参考一些文档。因为完成事件不会立即传播。

会为两者使用不同Scheduler的 sx并且y会对结果产生影响吗?

最后,我要介绍race吗?我对此表示怀疑,因为除非开发人员明确说明,否则 reactiveSwift 不会引入并发性。

4

1 回答 1

1

我整理了一个小示例控制台应用程序来测试它。正如我在评论中所说,take(first: 1)在传递 1 值事件后立即同步传递完成事件,这意味着ys 引用self将在任何值传递到之前消失x。假设这是对 , 的唯一强引用selfx将不会收到任何值。

import Foundation
import ReactiveSwift
import ReactiveCocoa

class MyClass {
    init(signal: Signal<String, Never>) {
        //call this observer y
        signal.take(first: 1).observeValues{ (value) in
            //intended strong capture on self. this is the only one that retains self so if this observer is triggered and completes, self should dealloc
            self.doSomethingElse(value) //trivial call, no async or thread hopping
        }

        //call this observer x
        signal.take(duringLifetimeOf: self).observeValues{ [unowned self] (value) in //is this safe or better to use weak and guard against it?
            self.doSomeProcess(value) //trivial call, no async or thread hopping
        }
    }

    func doSomethingElse(_ value: String) {
        print("Something Else: \(value)")
    }

    func doSomeProcess(_ value: String) {
        print("Some Process: \(value)")
    }
}

let (signal, input) = Signal<String, Never>.pipe()
_ = MyClass(signal: signal)

input.send(value: "1")
input.send(value: "2")

果然,doSomeProcess从不叫:

Something Else: 1
Program ended with exit code: 0

要记住的关键ReactiveSwift是,除非您使用一组特定的运算符或您自己的代码明确指定,否则一切都是同步发生的。因此,take操作员不会发送单值事件,然后以某种方式“安排”完成事件的交付以供以后使用。value 和完成事件的传递都发生在上游信号传递 value 事件的过程中,并且观察者及其引用的释放发生在signal完成传递其第一个事件之前。

当您说“完成事件不会立即传播”时,我假设您正在谈论APIContracts文件中有关如何立即传播故障和中断的部分。这只是注意到许多运算符会立即传递这些事件,即使它们是异步或时移运算符。

take运算符不是时移或异步运算符。在这种情况下,操作员不会从上游信号传播完成事件;相反,它自己生成完成事件,并且在传播值事件后立即同步执行

我在介绍比赛吗?

您是正确的,ReactiveSwift它本身并没有引入异步或并发,因此这里没有传统意义上的“种族”。但是,我相信 API 合约Signal并不能保证事件按照观察者开始观察的顺序传递给他们。因此,此代码的行为在技术上是未定义的,并且可能在未来版本的ReactiveSwift.

对 x 和 y 使用不同的调度程序会对结果产生影响吗?

现在这实际上会引入一场比赛,因为take' 的完成事件将在您为该观察者设置的任何调度程序上交付,并且该事件的交付将触发deinit.self

于 2019-06-26T15:42:15.577 回答