diff --git a/Documentation/DebuggingTechniques.md b/Documentation/DebuggingTechniques.md index d605844f8..2ef72f51b 100644 --- a/Documentation/DebuggingTechniques.md +++ b/Documentation/DebuggingTechniques.md @@ -15,7 +15,7 @@ Below is an example of type-error scenario: ```swift SignalProducer(value:42) - .on(next: { answer in + .on(value: { answer in return _ }) .startWithCompleted { @@ -23,12 +23,11 @@ SignalProducer(value:42) } ``` -The code above will not compile with the following error on a `print` call `error: ambiguous reference to member 'print' -print("Completed.")`. To find the actual compile error, the chain needs to be broken apart. Add explicit definitions of closure types on each of the steps: +The code above will not compile with the following error on the `.startWithCompleted` call `error: cannot convert value of type 'Disposable' to closure result type '()'. To find the actual compile error, the chain needs to be broken apart. Add explicit definitions of closure types on each of the steps: ```swift let initialProducer = SignalProducer.init(value:42) -let sideEffectProducer = initialProducer.on(next: { (answer: Int) in +let sideEffectProducer = initialProducer.on(value: { (answer: Int) in return _ }) let disposable = sideEffectProducer.startWithCompleted { @@ -36,45 +35,17 @@ let disposable = sideEffectProducer.startWithCompleted { } ``` -The code above will not compile too, but with the error `error: cannot convert value of type '(_) -> _' to expected argument type '(Int -> ())?'` on definition of `on` closure. This gives enough of information to locate unexpected `return _` since `on` closure should not have any return value. - -#### Binding `DynamicProperty` with `<~` operator - -Using the `<~` operator to bind a `Signal` or a `SignalProducer` to a `DynamicProperty` can result in unexpected compiler errors. - -Below is an example of this scenario: - -```swift -let label = UILabel() -let property = MutableProperty("") - -DynamicProperty(object: label, keyPath: "text") <~ property.producer -``` - -This will often result in a compiler error: - -> error: binary operator '<~' cannot be applied to operands of type 'DynamicProperty' and 'SignalProducer' -DynamicProperty(object: label, keyPath: "text") <~ property.producer - -The reason is a limitation in the swift type checker - A `DynamicProperty` always has a type of `AnyObject?`, but the `<~` operator requires the values of both sides to have the same type, so the right side value would have to be `AnyObject?` as well, but usually a more concrete type is used (in this example `String`). - -Usually, the fix is as easy as adding a `.map{ $0 }`. - -```swift -DynamicProperty(object: label, keyPath: "text") <~ property.producer.map { $0 } -``` - -This allows the type checker to infer that `String` can be converted to `AnyProperty?` and thus, the binding succeeds. +The code above will not compile too, but with the error `error: cannot convert value of type '(Int) -> _' to expected argument type '((Int) -> Void)?'` on definition of `on` closure. This gives enough of information to locate unexpected `return _` since `on` closure should not have any return value. #### Debugging event streams As mentioned in the README, stream debugging can be quite difficut and tedious, so we provide the `logEvents` operator. In its simplest form: ```swift -let searchString = textField.rac_textSignal() - .toSignalProducer() - .map { text in text as! String } - .throttle(0.5, onScheduler: QueueScheduler.mainQueueScheduler) +let property = MutableProperty("") +... +let searchString = property.producer + .throttle(0.5, on: QueueScheduler.main) .logEvents() ``` @@ -98,31 +69,32 @@ func debugLog(identifier: String, event: String, fileName: String, functionName: You would then: ```swift -let searchString = textField.rac_textSignal() - .toSignalProducer() - .map { text in text as! String } - .throttle(0.5, onScheduler: QueueScheduler.mainQueueScheduler) +let property = MutableProperty("") +... +let searchString = property.producer + .throttle(0.5, on: QueueScheduler.main) .logEvents(logger: debugLog) ``` We also provide the `identifier` parameter. This is useful when you are debugging multiple streams and you don't want to get lost: ```swift -let searchString = textField.rac_textSignal() - .toSignalProducer() - .map { text in text as! String } - .throttle(0.5, onScheduler: QueueScheduler.mainQueueScheduler) +let property = MutableProperty("") +... +let searchString = property.producer + .throttle(0.5, on: QueueScheduler.main) .logEvents(identifier: "✨My awesome stream ✨") ``` -There also cases, specially with [hot signals][[Signals]], when there is simply too much output. For those, you can specify which events you are interested in: +There also cases, specially with [hot signals][Signal], when there is simply too much output. For those, you can specify which events you are interested in: ```swift -let searchString = textField.rac_textSignal() - .toSignalProducer() - .map { text in text as! String } - .throttle(0.5, onScheduler: QueueScheduler.mainQueueScheduler) - .logEvents(events:[.Disposed]) // This will happen when the `UITextField` is released +let property = MutableProperty("") +... +let searchString = property.producer + .throttle(0.5, on: QueueScheduler.main) + .logEvents(events: [.disposed]) // This will happen when `property` is released ``` +[Signal]: ../Sources/Signal.swift