Hello ReactiveSwift(5): 调试技术 ——(
官方文档:
http://reactivecocoa.io/reactiveswift/docs/latest/index.html
实战项目:
https://github.com/JornWu/ZhiBo_Swift.git
一、整理Swift编译器错误
类型推断使编译器难以调试会错误,使用类型推断有两个潜在的地方出错:
1、定义类型推断的变量
2、使用类型推断的变量
在这两种情况下,错误与关于类型的不正确假设有关。这些问题对于ReactiveCocoa应用程序是常见的,因为它是关于数据和相关类型的操作。Swift编译器的当前状态可能导致误导类型错误,特别是当信号链中间发生错误时。
以下是类型错误情形的示例:
SignalProducer<Int, NoError>(value:42)
.on(value: { answer in
return _
})
.startWithCompleted {
print("Completed.")
}
上面的代码将不会在.startWithCompleted
调用error:
无法将类型'Disposable'
的值转换为闭包结果类型'()'
的时候出现以下错误。要找到实际的编译错误,链需要拆分。在每个步骤中添加关闭类型的显式定义:
let initialProducer = SignalProducer<Int, NoError>.init(value:42)
let sideEffectProducer = initialProducer.on(value: { (answer: Int) in
return _
})
let disposable = sideEffectProducer.startWithCompleted {
print("Completed.")
}
上面的代码因为存在error: cannot convert value of type '(Int) -> _' to expected argument type '((Int) -> Void)?'
在on
闭包定义中,也不会编译。这给出足够的信息来定位意想不到的return _
因为on
结束不应该有任何返回值。
二、调试事件流
如README所述,流调试可能相当困难和乏味,因此我们提供logEvents
操作。最简单的形式如下:
let property = MutableProperty<String>("")
...
let searchString = property.producer
.throttle(0.5, on: QueueScheduler.main)
.logEvents()
这将打印到标准输出的事件。对于大多数用例来说,这是足够的,将极大地帮助您了解您的流程。这种方法最大的问题是它将在Release模式下继续输出。这里你有两个选择:
注释操作://.logEvents()
。这是最简单的方法,但它很容易出错,因为你最终会忘记这样做。
通过你自己的功能,并按照你的看法操纵输出。这是推荐的方法。
让我们看看如果我们不想在Release模式下打印出来的话,
func debugLog(identifier: String, event: String, fileName: String, functionName: String, lineNumber: Int) {
// Don't forget to set up the DEBUG symbol (http://stackoverflow.com/a/24112024/491239)
#if DEBUG
print(event)
#endif
}
你会:
let property = MutableProperty<String>("")
...
let searchString = property.producer
.throttle(0.5, on: QueueScheduler.main)
.logEvents(logger: debugLog)
我们也提供identifier参数。当您调试多个流并且不想丢失时,这很有用:
let property = MutableProperty<String>("")
...
let searchString = property.producer
.throttle(0.5, on: QueueScheduler.main)
.logEvents(identifier: "✨My awesome stream ✨")
还有一些情况,特别是热信号,当输出太多时。对于那些,您可以指定您感兴趣的事件:
let property = MutableProperty<String>("")
...
let searchString = property.producer
.throttle(0.5, on: QueueScheduler.main)
.logEvents(events: [.disposed]) // This will happen when `property` is released