首页 > 解决方案 > 在避免状态的同时监视 UI 的最佳选择

问题描述

我对 Swift 和 iOS 开发相当陌生。我已经了解并渴望使用函数式编程来避免状态。因此,我正处于我旅程的一个阶段,我想问一个关于实现这一目标的编程技术的概念性问题。

假设我在由常规 UIViewController 控制的常规 UIView 上有一个常规 UISwitch。ViewController 类中的几个方法依赖于 UISwitch 的值来指示它们的精确操作。

我首先根据需要检查每个方法中的 UISwitch 的值,但是当这些方法在后台线程上异步调用时会导致警告。我知道我无法在后台线程上更改 UI,但似乎我也无法检查它的状态。

所以我求助于旧的最爱 - 类属性 - 来存储开关的当前状态,但感觉就像我这样做违背了函数式编程的基本原则。

然后,我意识到要让开关在应用程序关闭后用户离开时保持不变,我需要将其设置写入 UserDefaults。所以我可以在每次需要时从 UserDefaults 中获取值,但我担心的是,考虑到 iOS 需要来回切换到 UserDefaults,这种方法会相当慢。

所以,我的问题是:在我的 ViewController 的方法中获取 UISwitch 设置的最佳/最快/最不可能导致我未来问题的方法是什么?

  1. 每次需要检查开关时,通过调度到主线程来检查 UI
  2. 将值存储在类属性中,并挂起后果
  3. 每次需要时从 UserDefaults 获取值或
  4. 我尚未了解的任何其他方法

标签: iosswiftmodel-view-controllerfunctional-programming

解决方案


你是对的,在某处坚持重要的用户选择是更好的用户体验。不过,您不必担心使用UserDefaults它 - 它旨在用于存储那些简单的键值设置。此外,在您第一次加载它后,它不会使用物理内存 i/o - 您需要调用.synchronize它以使其发生(例如,当应用程序进入后台时)。

我建议两种方法:

第一个对初学者更友好的方法是设置一个像这样的变量:

var yourFlag : Bool {
    get {
        let defaults = Defaults.standard
        return defaults.bool(forKey: "yourFlagKey") 
    }

    set (newValue) {
        let defaults = Defaults.standard
        defaults.set(newValue, forKey: "yourFlagKey")
    }
}

这样你就可以像使用任何其他实例变量一样使用你的变量,但在引擎盖下它会使用UserDefaults. 例如,在您的开关值更改操作中,您可以简单地设置新值,它将保持为UserDefaults

func onValueChanged(sender: UISwitch) {
   yourFlag = !sender.on
}

我建议不要将此变量存储在您的 ViewController 中。我通常为我的所有用户设置创建一个容器类,这样我就可以在需要它们的任何地方检查它们。理想情况下,您希望将此容器作为UIViewController.

第二种方法(如果你真的想更深入地研究函数式编程)是学习如何使用像 RxSwift 这样的 FRP(函数式反应式编程)框架,并将值变化事件视为可观察的,你可以在其上构建你的流程。但是,如果您刚刚开始,我建议您学习以常规(苹果)方式做事,以便您了解 FRP 带来的好处和缺点。


推荐阅读