Isuru
Isuru

Reputation: 31283

'() -> BindingTarget<Error>' is not convertible to '(Bool) -> BindingTarget<Error>'

I recently inherited a iOS project written using ReactiveSwift 3.1.0 and ReactiveCocoa 7.2.0. I'm tasked with updating it to Swift 5 and the latest ReactiveSwift versions.

I updated ReactiveSwift to 6.1.0 and ReactiveCocoa to 10.1.0. I'm not well versed in Reactive programming but I managed to convert a good portion of the existing codebase to the latest versions.

However I'm stuck at this particular part. The original programmer is not available anymore.

In this project, there is an extension on view controller to present error messages.

extension Reactive where Base: UIViewController {
    func presentError(animated: Bool = true) -> BindingTarget<Error> {
        return self.makeBindingTarget { $0.present(error: $1, animated: animated) }
    }

    func present(error: Error, animated: Bool = true, completion: (() -> Void)? = nil) {
        LogError("Presenting error: \(error.verboseDescription)")
        self.present(UIAlertController(error: error, completion: completion), animated: animated, completion: nil)
    }
}

In a view controller, I'm getting the below error at this line.

self.reactive.presentError() <~ self.viewModel.reportAction.errors.map { $0 }

'() -> BindingTarget' is not convertible to '(Bool) -> BindingTarget'

This is the relevant part in the view model.

private(set) var reportAction: Action<(User, ReportReason), Void, APIKit.Error>!

The only change that happened here is the errors type in viewModel.reportAction.errors.map { $0 } changed from public let errors: Signal<Error, NoError> to public let errors: Signal<Error, Never>. This is due to some changes done in the latest ReactiveSwift source.

That has apparently broken this piece of code. I'm not sure why the error is occurring and how to fix this part.

Upvotes: 0

Views: 168

Answers (1)

Chris Brakebill
Chris Brakebill

Reputation: 36

I don’t think the present error method should be in the reactive extension but rather in an extension on UIViewController. Because the first argument in your binding target closure will be of whatever type Base is. So…

extension Reactive where Base: UIViewController {
    func presentError(animated: Bool = true) -> BindingTarget<Error> {
        return self.makeBindingTarget { $0.present(error: $1, animated: animated) }
    }
}

extension UIViewController {

    func present(error: Error, animated: Bool = true, completion: (() -> Void)? = nil) {
        LogError("Presenting error: \(error.verboseDescription)")
        self.present(UIAlertController(error: error, completion: completion), animated: animated, completion: nil)
    }
}

Upvotes: 0

Related Questions