我对Swift和iOS开发相当陌生。我已经了解并渴望使用函数式编程来避免状态的目标。因此,在我的旅程中,我想提出一个有关实现这一目标的编程技术的概念性问题。
说我在常规UIView上有一个常规UISwitch,该UISwitch由常规UIViewController控制。 ViewController类中的几种方法取决于UISwitch的值来指示其精确的操作。
我首先根据需要检查每个方法中的UISwitch的值,但是当在后台线程上异步调用这些方法时会产生警告。我知道我无法在后台线程上对UI进行更改,但是似乎我也无法检查其状态。
所以我求助于旧的最喜欢的类属性来存储开关的当前状态,但是这样做似乎违反了函数式编程的基本原理。
然后,我意识到要允许该开关在关闭应用程序后仍保留在用户离开时的状态,我需要将其设置写入UserDefaults中。因此,每次需要时,我都可以从UserDefaults中获取值,但是我担心的是,鉴于需要iOS往返于UserDefaults,这种方法的速度要慢得多。
所以,我的问题是:在我的ViewController方法中获取UISwitch设置的最佳/最快/最可能导致我未来问题的方法是什么?
答案 0 :(得分:1)
您是对的,最好将UX保留在重要位置的用户选择。不过,您不必担心使用UserDefaults
-它是用于存储那些简单的键值设置的。另外,它在第一次加载后并没有使用物理内存-您需要调用.synchronize
才能使它发生(例如,当应用程序进入后台时)。
我建议2种方法:
第一种更适合初学者的方法是设置一个像这样的变量:
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带来的好处和缺点。
答案 1 :(得分:0)
我建议的方法是拥有一个Bool
属性,以保持Switch对象的状态。只要开关控件的状态发生更改,就对其进行更新。
这些方法中的任何一种都应访问Bool
属性,而不是直接访问开关控件的状态。
将UserDefaults用于需要保留的几个设置就可以了。我建议从viewDidLoad()
内的“用户默认设置”中加载“切换控件”的初始值,但只要View Controller即将消失或应用程序本身进入后台或即将关闭,就设置最新的值。之所以被销毁,是因为“用户默认设置”在幕后使用了.plist
,任何操作都可能花费比预期更长的时间,有时甚至可能导致意外行为。
此外,您可以使用包含该SettingStateController
属性和其他内容的Bool
类。让它从初始化器中的“用户默认值”初始化所有属性,并在释放其实例时将其保存到“用户默认值”。这样,访问将更快,并且代码将基于不同的关注点进行分离。 View Controller
的行为应更像视图,如上所述,决定使用User Default,本地文件,Core Data等的责任应在单独的类中实现。