Search code examples
swiftenumscombinepublisher

Using a Published var to observe a switch case in a Publisher with Combine


I have an enum case which is a @Published var in an ObservableObject class. What I'm trying to do is observe changes to the term var defined below and update an annualRate publisher.

Below is the @Published var

@Published var term: MortgageTerm = .thirtyYear

The MortgageTerm enum is defined as follows:

public enum MortgageType: Int, CaseIterable {
    case tenYear     = 10
    case fifteenYear = 15
    case twentyYear  = 20
    case thirtyYear  = 30
}

I'm trying to get this annualRate defined so it observes changes to the term var above:

public lazy var annualRate: AnyPublisher<Double, Never> = {
    var output: Double
    $term
        .map { switchCase -> Double in
            switch switchCase {
            case .tenYear:
                output = self.rates.tenYearFix
            case .fifteenYear:
                output = self.rates.fifteenYearFix
            case .twentyYear:
                output = self.rates.twentyYearFix
            case .thirtyYear:
                output = self.rates.thirtyYearFix
            }
            
            return output * 0.01
        }
        // FIXME: Result of call to `eraseToAnyPublisher()` is unused
        .eraseToAnyPublisher()
}()

I'm getting this warning at the line for .eraseToAnyPublisher(). What am I mucking up and how do I fix it?

This is where the rates are coming from:

private lazy var rates: AverageRate = {
    let rateMock = AverageRate(thirtyYearFha: 2.873,
                                thirtyYearVa: 2.858,
                                tenYearFix: 2.068,
                                fifteenYearFix: 2.358,
                                thirtyYearFix: 3.054,
                                fiveOneArm: 2.898,
                                sevenOneArm: 2.972,
                                twentyYearFix: 2.756)
    
    return rateMock
}()

Solution

  • Right now, you don't have a return statement inside your annualRate { }. You have two statements -- one defining output and the second creating the publisher. If you just had one statement, it would be considered an implicit return and you wouldn't have the error.

    I think you can refactor very slightly and get rid of the var output since every value is getting modified by the same amount. So, you can just tack on another map:

    public lazy var annualRate: AnyPublisher<Double, Never> = {
        $term
            .map { switchCase -> Double in
                switch switchCase {
                case .tenYear:
                    return self.rates.tenYearFix
                case .fifteenYear:
                    return self.rates.fifteenYearFix
                case .twentyYear:
                    return self.rates.twentyYearFix
                case .thirtyYear:
                    return self.rates.thirtyYearFix
                }
            }
            .map { $0 * 0.01 }
            .eraseToAnyPublisher()
    }()
    

    Now, there's just one statement, which is considered an implicit return and nothing is unused.