是否可以根据从 Swift 中的 UIViewController 继承的类中的另一个来初始化变量?

Posted

技术标签:

【中文标题】是否可以根据从 Swift 中的 UIViewController 继承的类中的另一个来初始化变量?【英文标题】:Is it possible to initialize variable depending on another in class inheriting from UIViewController in Swift? 【发布时间】:2020-05-02 13:48:15 【问题描述】:

我正在尝试实现一件看似简单的事情:使用继承自 UIViewController 的同一类中的另一个变量来初始化常量变量。我有 2 个可行的想法,但存在问题并且似乎不是最佳解决方案。

想法 1 - 问题:不是恒定的

class MyViewController: UIViewController 
    let db = Firestore.firestore()
    let uid: String = UserDefaults.standard.string(forKey: "uid")!
    lazy var userDocRef = db.collection("users").document(uid)

想法 2 - 问题:不是恒定的并且是可选的

class MyViewController: UIViewController 
    let db = Firestore.firestore()
    let uid: String = UserDefaults.standard.string(forKey: "uid")!
    var userDocRef: DocumentReference?
    override func viewDidLoad() 
        super.viewDidLoad()
        userDocRef = db.collection("users").document(uid)
    

我认为应该可以通过覆盖init() 来实现这一点。我已经尝试了几个我发现谷歌搜索的实现,但是我尝试过的每个人都给了我一些错误。几个例子:

From this answer.

convenience init() 
    self.init(nibName:nil, bundle:nil) // error: Argument passed to call that takes no arguments
    userDocRef = db.collection(K.Firestore.usersCollection).document(uid)

From this article.

required init(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)! // Property 'self.userDocRef' not initialized at super.init call


init() 
   super.init(nibName: nil, bundle: nil) // Property 'self.userDocRef' not initialized at super.init call
   userDocRef = db.collection(K.Firestore.usersCollection).document(uid)

我猜我要么遗漏了一些东西,要么那些东西已经过时了?我很惊讶这样一个简单的任务,因为重写初始化程序是如此的麻烦。正确的做法是什么?

【问题讨论】:

【参考方案1】:

您的第二次尝试非常接近。你真的错过了这条你必须遵守的规则:

您的类中声明的所有属性必须在调用super.init之前进行初始化。

在您的第二次尝试中,userDocRef 未在 init(coder:) 中初始化,而是在init() 中的super.init 调用之后初始化。

你应该这样写:

init() 
    userDocRef = db.collection(K.Firestore.usersCollection).document(uid)
    super.init(nibName: nil, bundle: nil)


required init?(coder: NSCoder) 
    userDocRef = db.collection(K.Firestore.usersCollection).document(uid)
    super.init(coder: coder)

我不认为你可以摆脱这里的重复代码......你能做的最好的事情就是创建一个返回db.collection(K.Firestore.usersCollection).document(uid)静态辅助方法,这意味着使@987654328 @static 也是如此,现在我想起来可能会更糟。

请注意,故事板中的任何内容都将使用init(coder:) 创建,因此如果您使用故事板,请务必在此处正确执行初始化程序。

【讨论】:

"如果您使用情节提要,请务必在此处正确执行初始化程序" 我不确定这意味着什么?我正在使用故事板。我是否必须以某种方式在代码的初始化程序中初始化情节提要中的元素? @Stormwaker 不,我的意思是您应该实现init(coder:) 正确,同时初始化需要初始化的属性,就像我在回答中所做的那样。与您所做的不同,即不初始化 init(coder:) 中的任何内容。我试图指出您实际上应该更多地关注init(coder:),因为那是实际调用的初始化程序。除此之外,我的回答有效吗?

以上是关于是否可以根据从 Swift 中的 UIViewController 继承的类中的另一个来初始化变量?的主要内容,如果未能解决你的问题,请参考以下文章

MKPointAnnotations 快速触摸事件

是否可以以编程方式从 Swift/Objective-C 中的 UIViewController 或 Storyboard 中获取基本 UIViewController 的标识符?

如何根据 API 级别从 Swift 中的两个不同类派生一个类?

AlamofireImage:是不是可以从 Swift 中的 NSimageview 获取原始数据?

是否可以将Swift 4.1添加到Xcode 10中

Swift中的自动完成搜索列表问题