skip to Main Content

Based on this question, it’s not the way to go but how do I go about handling this so I can update UI elements when said property is update.

This would easily be achieved in SwiftUI using @Published

    var exchangeRate: Double = 1.0 {
    willSet {
        guard let doubleFormattedValue = Double.format(newValue, numberStyle: .decimal, decimalPlaces: 6) else { return }
        DispatchQueue.main.async {
            self.rateLabel.text = String(doubleFormattedValue) + " " + self.fromCurrencyTextField.currency.rawValue
        }
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    Following the suggestion of @Paulw11 and this tutorial, I was able to implement the following:

    private var viewModel: CurrencyConverterViewModel = CurrencyConverterViewModel()
    private var subscriptions = Set<AnyCancellable>()
    
    private func configureBinding() {
    
        viewModel.$exchangeRate
            .sink { [weak self] exchangeRate in
                guard let self = self else { return }
                // UI changes go here
            }
            .store(in: &subscriptions)
    }
    

  2. ViewModel shouldn’t have any inforamtion about the View you can use binding with change handler and escaping, this solution is without combine or rxswift or async await etc.

    such as:

    enum SampleViewModelChange {
        case didValueChanged
        case didError(Error)
        case didEverythingYouWant
    }
    
    final class SampleViewModel {
        var sampleChangeHandler: ((SampleViewModelChange) -> Void)?
    
       var exchangeRate: Double = 1.0 {
           willSet {
              emitSample(.didValueChanged)
           }
           didSet {
              emitSample(.didEverythingYouWant)
           }
       }
    
        func emitSample(_ change: SampleViewModelChange) {
            sampleChangeHandler?(change)
        }
    }
    
    

    in your view you can have:

    class SampleVC: UIViewController {
        var viewModel: SampleViewModel
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
            bindViewModel()
        }
    
    
        func bindViewModel() {
            viewModel.sampleChangeHandler = { [weak self] change in
                guard let strongSelf = self else { return }
                switch change {
                case .didValueChanged:
                    debugPrint(didValueChanged)
                    self.rateLabel.text = String(doubleFormattedValue) + " " + self.fromCurrencyTextField.currency.rawValue
         
                case .didError(let error):
                    debugPrint(error)
                case .didEverythingYouWant:
                    debugPrint(EverythingYouWant such as reload table or every thing you want)
                }
            }
        }
    
    }
    
    

    To me MVVM does not depend on UIView or SwiftUI or Snappkit, you can use MVVM with every UI that you want. this is a general Architecture.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search