gpt4 book ai didi

Swift init 无限循环,默认常量值

转载 作者:行者123 更新时间:2023-11-30 10:21:09 25 4
gpt4 key购买 nike

我有 UIViewController 子类。我有一个想要延迟加载的常量。为此,我使用一个函数来设置它的默认值。我在这里有两个 init 方法,因为我之前使用它们来设置值。然后我发现我无法调用通用方法来设置该值。似乎只有 init 方法可以设置类常量的值。当我创 build 置默认值的函数时,我发现有一个无限循环,它从 init(nibName, bundle) 函数重复调用我的函数来实现目标。我是 Swift 新手,不确定我做错了什么。

class ViewController: UIViewController {

let goal: Goal =
{
return Goal()
}()

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)
{
super.init()
}

required init(coder decoder: NSCoder)
{
super.init()
}
}

最佳答案

当您重写方法时,您应该调用该方法的 super 实现。

required override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}

常量 let 值只能在初始值设定项中设置。如果您有超过 1 个初始化程序,请考虑如何链接它们。拥有 1 个指定的初始化程序和许多便利非常有用。通过这种方式,您只需在一处设置变量。 示例

class A {

let age: Int
let name: String
let type: String

init(age: Int, name: String, type: String) {
self.age = age
self.type = type
self.name = name
}

convenience init() {
self.init(age: 0, name: "", type: "")
}
convenience init(age: Int) {
self.init(age: age, name: "", type: "")
}
convenience init(age: Int, name: String) {
self.init(age: age, name: name, type: "")
}

在 swift 中,你必须在 init 方法中完全初始化类。这意味着您必须为所有属性设置值并调用 super init(如果存在)。之后您可以访问 self 和 call 方法。

在 Cocoa 框架中,类有不止一种方法来实例化它们,并且有许多初始化程序。示例 UIViewController 有
init(nibName:String?,bundle:NSBundle?)init(coder:NSCoder)我们如何初始化这个类?

  1. 设置变量值

这个解决方案有 1 个巨大的缺点 - 它不是 DRY
您在 2 个地方有相同的代码。如果您需要更改或修复它,则需要在 2 个地方执行相同的操作。非常糟糕的架构和代码味道。

var name: String

required init(coder aDecoder: NSCoder) {
name = "Name"
super.init(coder: aDecoder)
}

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
name = "Name"
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

我们能做得更好吗?解决方案看起来很明显 - 在单独的方法中提取名称初始化。但我们不能这样做,因为 Swift class安全规则
初始化步骤

  1. 设置所有属性
  2. 调用 super.init(...)
  3. 现在您的类和父类(super class)都已完全初始化。只有在这里你才能访问 self 并调用 self 的方法

代码:

 required init(coder aDecoder: NSCoder) {
setDefaultName() // Error. Can't access self yet
super.init(coder: aDecoder)
}

func setDefaultName() {
name = "Name"
}
  • 默认值
  • 设置变量的默认值。
    这看起来更好,因为我们只在一处初始化属性。

     var name: String = ""

    required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }

    如果您需要更复杂的逻辑来初始化变量,您可以使用闭包。
    我不喜欢这样,因为现在你的类变量声明中有逻辑(与函数相同的闭包)。
    我们可以做得更好吗?我们可以!

     var name: String = {
    var name = "Name"
    // ....
    // Other complicated logic
    name + " Is Best"
    return name
    }()
  • 工厂方法
  • 最好采用该闭包并将其移到类变量定义之外,
    所以我们可以做类似的事情 var name = Factory.defaultName()

    Swift 支持内部类。您可以在类中创建类。通过这种方式,您可以将一些功能分组到一个类中。这听起来非常适合将初始化方法分组到工厂类中
    最终示例:

    var name: String = Factory.defaultName()

    required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }


    class Factory {
    class func defaultName () -> String {
    return "Name"
    }
    }

    关于Swift init 无限循环,默认常量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26450630/

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