视图如何更新viewcontroller?

Wil*_*ken 9 model-view-controller ios swift

我从CS193P课程中学到了Swift.它建议使用以下API来使ViewController FaceViewController更新其视图FaceView:

var expression = FacialExpression(eyes: .Closed, eyeBrows: .Relaxed, mouth: .Smirk) {
    didSet {
        updateUI() // Model changed, so update the View
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当视图更新自己的模型时,我还没有看到这个概念的扩展.例如,这没有意义:

// Implementing an imaginary delegate UIFaceViewDelegate
func faceView(_ faceView: FaceView, didEpdateExpressionTo expression: FacialExpression {
    self.expression = expression
    // This triggers another update to the view, and possibly infinite recursion
}
Run Code Online (Sandbox Code Playgroud)

在Objective-C中,这非常简单,因为您可以将getter和setter用作公共API,将后备存储用作私有状态.Swift也可以使用计算变量来使用这种方法,但我相信Swift设计师有一些不同的想法.

那么,视图控制器在响应视图更新时表示状态更改的适当方式是什么,同时还为其他人公开合理的读/写API以检查其状态?

Han*_*nge 8

我还观看了cs193p2017年冬季视频.对于FaceIt应用程序,mdoel需要转换为how it will be displayed on the view.它不是1 to 1 翻译,而是更像3 to 2或类似的东西.这就是我们有辅助方法的原因updateUI(_:).

关于如何根据变化进行view controller更新的问题.在这个例子中,我们无法更新,因为我们需要弄清楚?如果我们想要持久性,我们可以只存储in 或.modelviewmodelhow to map 2 values to 3 valuesview statecore datauserDefaults

在更一般的设置中,model change need to update the viewview change need to update the model,然后我们需要indirection避免cycle像你想象的那样.

例如,因为它FacialExpression是值类型.我们可以有类似的东西:

private var realExpression = FacialExpression(eyes: .Closed, eyeBrows: .Relaxed, mouth: .Smirk)
var expression: FacialExpression  {
    get { return realExpression } 
    set { 
         realExpression = newValue 
         updateUI() // Model changed, so update the View
    }  
}
Run Code Online (Sandbox Code Playgroud)

}

然后在你的 imaginary delegate UIFaceViewDelegate我们可以有以下内容:

// Implementing an imaginary delegate UIFaceViewDelegate
func faceView(_ faceView: FaceView, didEpdateExpressionTo expression: FacialExpression {
    self.realExpression = expression
// This WILL NOT triggers another update to the view, and AVOID THE possibly of infinite recursion
Run Code Online (Sandbox Code Playgroud)

}


sim*_*one 3

以下是我的测试代码:

class SubView:UIView{

}

class TestVC: UIViewController {
    var testView : SubView = SubView.init(frame: CGRect.zero)  {
        didSet{
            print("testView didSet")
        }
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

        var testBtn = UIButton.init(frame: CGRect(x: 0, y: 0, width: 264, height: 45))
        testBtn.backgroundColor = .red
        testBtn.addTarget(self, action: #selector(clickToUpdateTestView), for: UIControlEvents.touchUpInside)
        self.view.addSubview(testBtn)
    }

    func clickToUpdateTestView() -> Void {
        self.testView = SubView.init(frame: CGRect.zero)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
Run Code Online (Sandbox Code Playgroud)

但是当单击按钮时,我在控制台输出中得到“ testView didSet ”。和你的工具有什么区别?