【问题标题】:Swift Optional Checking "Unexpectedly found nil"Swift 可选检查“意外发现 nil”
【发布时间】:2015-01-15 02:45:31
【问题描述】:

我不确定为什么 Swift 在我的 if 语句检查 list1 != nil 时会抱怨 list1 = list1!.next 意外发现 nil。谁能解释为什么检查 list1 != nil 是不够的?我试过把它改成

if list1 {
    list1 = list1!.next
}

但它建议我使用 != nil 进行检查

Here's a gist

这是我的代码:

class Node {
    var data: Int
    var next: Node?

    init (data: Int) {
        self.data = data
    }
}

func addReversed (var list1: Node?, var list2: Node?) -> Node {
    var carry = 0
    var head: Node? = nil
    var prev: Node? = nil
    while list1 != nil || list2 != nil {
        var newNode = addNode(list1, list2, &carry)
        appendNode(head, prev, newNode)
        if list1 != nil {
            list1 = list1!.next
        }
        if list2 != nil {
            list2 = list2!.next
        }
    }
    if carry > 0 {
        var carryNode = Node(data: carry)
        appendNode(head, prev, carryNode)
    }
    return head!
}

【问题讨论】:

  • 你不能说if list1。它不是布尔值。你不能像那样进行零检查。 (你可以在早期的 Swift 中使用,但他们取消了它,这是正确的。)
  • 您能多描述一下 Node 吗?
  • 您正在返回 head!,但除了 nil 之外,您从未为其分配任何内容
  • 修改另一个函数中的变量不会影响这个函数中的局部变量
  • 我认为你的appendNode 函数有缺陷。

标签: ios swift


【解决方案1】:

这不是你问的,但我认为这可能与问题有很大关系。我测试了您的 Node 和基本的 addReversed 代码,但没有崩溃。但是当时我没有你的任何其他全局函数,所以我不得不在测试时将它们注释掉。由于我没有崩溃,因此我开始相信问题出在 那些全局函数之一中。

然后你发布了你的要点,以及这些全局函数的代码,我可以立即看到这段代码存在严重缺陷:

func appendNode(var head: Node?, var prev: Node?, node: Node) {
    if head == nil {
        head = node
    }
    if prev == nil {
        prev = node
    }
    else {
        prev!.next = node
        prev = node
    }
}

你似乎认为这句话,例如prev = node 将在某些外部世界中将作为 prev 传入的节点替换为以 node 传入的节点。它不会。这些只是局部变量的名称。因此,这些代码都没有任何效果——除了prev!.next = node,因为你正在改变一个也存在于外部世界中的实例(因为这是一个引用类型,一个类实例)。

如果你想用另一个对象替换一个参数中的对象,你需要一个inout参数。

例如:

class Dog {
    let name:String
    init(_ s:String) {
        name = s
    }
}

func replaceDog(var d:Dog) {
    d = Dog("Rover") // this is what you are doing
}

var d = Dog("Fido")
replaceDog(d)
d // still Fido

但是:

class Dog {
    let name:String
    init(_ s:String) {
        name = s
    }
}

func replaceDog(inout d:Dog) {
    d = Dog("Rover")
}

var d = Dog("Fido")
replaceDog(&d)
d // Rover

你的代码充满了同样的错误假设,我认为,虽然我没有弄清楚细节,但这个假设是你在这里遇到困难的原因。我的猜测是,您从其他具有指针的语言中获得了此链表实现,但您没有在实现中使用指针。在 Swift 中使用指针的方法是 inout!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-22
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多