gpt4 book ai didi

ios - 在 Swift/iOS 中使用前初始化类属性

转载 作者:行者123 更新时间:2023-11-28 07:03:24 25 4
gpt4 key购买 nike

我无法掌握实例化变量的正确方法,这些变量总是需要在对象完全发挥作用之前设置,但可能需要在构造函数之后实例化。根据 Swift 的其他约定和限制,似乎有一种我不知道的设计模式。

这是我的用例:

  • 我有一个继承自 UIViewController 的类,它将根据用户操作以编程方式创建 View
  • 我需要将这些 View 附加到此类,但为此我需要根据另一个 Controller 提供的配置数据检索它们的内容
  • 我不关心这个配置数据是传递给构造函数(在这种情况下总是需要它)还是在使用之前由对该对象的二次调用提供

我的问题似乎是第 3 条中的两种方法似乎都有缺陷。

在第一种情况下,只有一个合法的构造函数可以调用这个类,但我不得不覆盖其他构造函数并使用假值初始化成员变量,即使其他构造函数从未打算使用(我我还试图根据 Swift 的最佳实践将这些变量保留为 let 类型。

在第二种情况下,我有效地将我的构造函数分成两部分,并引入一个额外的失败点,以防第二部分在使用类之前调用​​失败。我也无法将第二部分移动到保证在使用前调用的方法(例如 viewDidLoad),因为我仍然需要从配置中传递额外的参数。虽然我可以确保手动调用 initPartTwo,但我更希望有一种机制可以更好地将它与实际构造函数分组。我不是第一个遇到这个问题的人,似乎有一种我没有看到的模式可以使它更清洁。

更新:我最终采用了 matt 建议的模式的修改版本:

struct Thing {
let item1: String
let item2: String
struct Config {
let item3: String
let item4: String
}

var config:Config! {
willSet {
if self.config != nil {
fatalError("tried to initialize config twice")
}
}
}

init() {
self.item1 = ...
self.item2 = ...
...
}

public func phaseTwoInit(item3: String, item4: String) {
self.item3 = item3
self.item4 = item4
...
}
}

var t = Thing()
...
t.phaseTwoInit(...)
...
// start using t

最佳答案

如果无法在对象初始化时提供初始实例变量属性值,通常的做法是将其声明为 Optional。这样它就不需要被类的初始化器初始化(它有一个值 - 它自动为 nil),而且你的代码随后可以区分未初始化的(nil)来自已初始化(不是 nil)。

如果 Optional 是隐式解包的 Optional,则这种安排对您的代码没有特别的影响(即它不必被解包)。

如果你的反对意见是你被迫打开这个实例变量的多个设置的大门,因为现在它必须用 var 声明,那么用一个 setter observer 关上这扇门:

struct Thing {
var name:String! {
willSet {
if self.name != nil {
fatalError("tried to set name twice")
}
}
}
}
var t = Thing()
t.name = "Matt" // no problem
t.name = "Rumplestiltskin" // crash

关于ios - 在 Swift/iOS 中使用前初始化类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31467989/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com