父/子关系的Swift:Init()模式 安装程序
假设我有两个班:父/子关系的Swift:Init()模式 安装程序,swift,initialization,Swift,Initialization,假设我有两个班: final class Parent: NSObject { var child: Child } final class Child: NSObject { weak var parent: Parent? init(parent: Parent) { self.parent = parent } } 问题: 现在假设我想实例化一个子并在Parent的init()方法中建立这个关系。我会这样做: final class
final class Parent: NSObject
{
var child: Child
}
final class Child: NSObject
{
weak var parent: Parent?
init(parent: Parent)
{
self.parent = parent
}
}
问题: 现在假设我想实例化一个子
并在Parent
的init()
方法中建立这个关系。我会这样做:
final class Parent: NSObject
{
var child: Child
init()
{
child = Child.init(parent: self) // ERROR!
}
}
斯威夫特抱怨说我在super.init()
之前使用了self
。如果我在实例化child
之前放置super.init()
,Swift抱怨说child
在super.init()
调用中没有赋值
我一直在使用隐式展开选项来关闭Swift,如下所示:
final class Parent: NSObject
{
var child: Child!
init()
{
super.init()
child.init(parent: self)
}
}
我的问题是:在这种情况下人们会做什么?这是/曾经是Objective-C中非常常见的模式,Swift只会让人头痛。我知道我可以将parent
的赋值从Child
的init()
中分离出来,这样我就可以init()
Child,调用super.init()
,然后分配parent
,但在我遇到这种情况的现实世界中,这不是一个选项。它也是丑陋和臃肿的
我确实意识到Swift的意图是在对象完全初始化之前阻止使用它。而且child
的init()
可以回调到parent
并访问尚未设置的状态,这对于隐式展开的可选方法来说是一种危险
我在这里找不到任何关于Swift最佳实践的指导,所以我想问人们如何解决这个鸡和蛋的问题。将属性转换为隐式展开的选项真的是绕过此限制的最佳方法吗?谢谢。你可以让它变得懒惰
,你所有的头痛都会过去的
final class Parent {
lazy var child = Child(parent: self)
}
final class Child {
weak var parent: Parent?
init(parent: Parent) {
self.parent = parent
}
}
在Swift中,应在self
可用之前初始化所有存储的属性。在超类
中包括存储的属性。所以Xcode直到那时才允许您使用self
。但是使用lazy
意味着它之前已初始化。因此,您可以自由使用self
一些有用的注释:
objc
高级功能,请不要从NSObject
继承(
将在objective-C中读作with
。因此您不需要在初始值设定项中使用with parent
作为标签还要注意的是,上面的一些注释是在注释之前写的,你可以让它变得懒惰,你所有的烦恼都会消失
final class Parent {
lazy var child = Child(parent: self)
}
final class Child {
weak var parent: Parent?
init(parent: Parent) {
self.parent = parent
}
}
在Swift中,所有存储的属性都应该在self
可用之前初始化。将存储的属性包括在超类中
。因此Xcode在此之前不允许您使用self
。但是使用lazy
意味着它之前就已经初始化。因此,您可以自由使用self
一些有用的注释:
objc
高级功能,请不要从NSObject
继承(
将在objective-C中读作with
。因此您不需要在初始值设定项中使用with parent
作为标签还请注意,上面的一些注释是在注释之前编写的为什么要从
NSObject
继承?可能有帮助:,。在您的情况下,这将是lazy var child=child(withParent:self)
因为,在我非平凡的现实世界中,我使用从NSObject继承的类,而这些类需要从某些东西继承才能使用super.init()。我已经将我的示例简化为我可以组装的最小情况。懒惰并不是我想要的。我希望“child”从“parent”开始就存在;我不想等到我第一次打电话给“child”来设置它。Joe Groff在Swift论坛的一篇文章中写道:“IUO历来是处理循环引用的答案……现在,一个属性包装器……可能是最好的方式。”为什么要从NSObject
继承?可能有帮助:,。在您的情况下,这将是lazy var child=child(withParent:self)
,因为在我的非平凡的实际情况中,我使用的类是从NSObject继承的,并且这些类需要从super.init()的某些内容继承需要。我已经把我的例子浓缩到了我能收集到的最起码的案例。懒惰并不是我想要的。我希望“孩子”从“家长”一开始就存在;我不想等到我第一次打电话给“孩子”来建立它。来自Swift论坛a中的Joe Groff:“IUO在历史上一直是处理循环引用的答案,……现在,属性包装器……可能是最好的方式。”同样,我有很好的理由希望在创建“child”时它存在。我不希望它延迟到我第一次调用它。例如,child的“init()”的其余部分方法分派一个异步请求以从远程服务器下载一些数据。我希望该过程立即启动。将“\u=self.child”添加到父级的“init()”底部以启动lazy属性似乎很愚蠢。最常见的情况是具有“init(delegate:)”的情况方法。我通常希望代理是我,我正在尝试在我自己的“init()中设置它方法.Delegate是一个弱的
属性。您可以将parent设置为可选的,并且可以在初始值设定项中自由使用self。但我认为这不是您想要的。同样,我有很好的理由希望在创建“child”时让它存在。我不希望它延迟到第一次调用它。例如,child的其余部分的“init()”方法调度一个异步请求以从远程下载一些数据