Swift可选检查“意外发现零”

时间:2015-01-15 02:45:32

标签: ios swift

我不确定为什么Swift抱怨list1 = list1!.next意外地发现nil,当我的if语句检查list1!= 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!
}

1 个答案:

答案 0 :(得分:0)

这不是你问的问题,但我认为这可能与问题有很大关系。我测试了你的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