即使在保护自我和非可选属性之后,也可以获得“初始化前使用的变量'self.xxx'”

时间:2019-02-21 23:59:21

标签: swift mvvm rx-swift coordinator-pattern

我目前正在为用Swift编写的新应用程序实现MVVM(使用Rx)体系结构,并且在编写ViewModel时遇到了麻烦。

这是它的开始:

class GameViewModel {
    public let input: Input
    public let output: Output

    public struct Input {
        let slider: AnyObserver<Float>
        let buttonCLicked: AnyObserver<Void>
    }

    public struct Output {
        let slider: Observable<Float>
        let target: Observable<Int>
        let score: Observable<Int>
        let round: Observable<Int>
        let buttonCLicked: Observable<AlertProperties>
    }

    private var slider = BehaviorSubject<Float>(value: 0)
    private var buttonCLicked = PublishSubject<Void>()
    private var target = BehaviorSubject<Int>(value: 0)
    private var score = BehaviorSubject<Int>(value: 0)
    private var round = BehaviorSubject<Int>(value: 0)

    private let disposebag: DisposeBag
    private var model: Game!

    init(game: Game?) {
        disposebag = DisposeBag()

        input = Input(slider: slider.asObserver(),
                      buttonCLicked: buttonCLicked.asObserver())

        output = Output(slider: slider.asObservable(),
                        target: target.asObservable(),
                        score: score.asObservable(),
                        round: round.asObservable(),
                        buttonCLicked: buttonCLicked.map { [weak self] _ in
                            guard let self = self else {
                                return AlertProperties(title: "Fail",
                                                       message: "!!!",
                                                       buttonTitle: "Ok",
                                                       handler: nil)
                            }
                            return self.getAlertProperties() })

        model = game ?? initDefaultGame()

        slider.onNext(Float(model.slider))
        target.onNext(model.target)
        score.onNext(model.score)
        round.onNext(model.round)
    }

这是一个基本函数,它使用当前值来创建要返回的对象:

    func getAlertProperties() -> AlertProperties {
        guard let targetValue = try? target.value(),
            let currentValue = try? slider.value() else {
            return AlertProperties(title: "Fail",
                                   message: "!!!",
                                   buttonTitle: "Ok",
                                   handler: nil)
        }

        // some code

        return AlertProperties(title: title,
                               message: "\(points) points: \(castCurrentValue)",
                               buttonTitle: "Ok",
                               handler: {
                                   self.target.onNext(self.getRandomValue())
                                   self.slider.onNext(50.0)
        })
    }

我在这里想要做的是在我的init函数上注册我的输入和输出。对于输出部分,我想使用一些当前值( getAlertProperties )传递函数的结果。 基本上,我在ViewController上有一个触发器,当用户单击一个简单的按钮时,需要将这些值显示在AlertController中。

对于输出中的buttonClicked声明,我收到错误消息在初始化之前使用的变量'self.xxx'。我得到在使用之前,我需要初始化所有非可选属性。自我,但我认为也许可以使用警卫来解决问题。显然不是...

如何在不使属性为 input output 可选的情况下解决此问题?

谢谢

1 个答案:

答案 0 :(得分:0)

好吧,我将属性输入和输出设置为惰性,并且可以正常工作。

    static let errorAlertProperties = AlertProperties(title: "Fail",
                                                      message: "!!!",
                                                      buttonTitle: "Ok",
                                                      handler: nil)

    lazy var input = Input(slider: slider.asObserver(),
                           buttonCLicked: buttonCLicked.asObserver(),
                           resetCLicked: resetClicked.asObserver())

    lazy var output = Output(slider: slider.asObservable(),
                             target: target.asObservable(),
                             score: score.asObservable(),
                             round: round.asObservable(),
                             buttonCLicked: buttonCLicked.map { [weak self] _ in
                                 guard let self = self else {
                                     return GameViewModel.errorAlertProperties
                                 }
                                 return self.getAlertProperties() })

我不知道这是否是“正确”的方法,所以请告诉我您是否有更好的方法。

谢谢