Ios 在展开可选值时意外发现nil(无法确定是哪个部分)

Ios 在展开可选值时意外发现nil(无法确定是哪个部分),ios,swift,optional,Ios,Swift,Optional,我是Swift的新手,我不知道我打开了哪个可选变量,我给它分配了nil,我试图在操场上调试它,但它不允许我逐步完成代码 致命错误:在展开可选值时意外发现nil public class ListNode { public var val: Int public var next: ListNode? public init() { self.val = 0; self.next = nil; } public init(_ val: Int) { self.val

我是Swift的新手,我不知道我打开了哪个可选变量,我给它分配了nil,我试图在操场上调试它,但它不允许我逐步完成代码

致命错误:在展开可选值时意外发现nil

public class ListNode {
    public var val: Int
    public var next: ListNode?
    public init() { self.val = 0; self.next = nil; }
    public init(_ val: Int) { self.val = val; self.next = nil; }
    public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
}
class Solution {
    func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
        let result = ListNode()
        var resultTail = result
        var carry: Int = 0
        var out: Int = 0
        var val1: Int = 0
        var val2: Int = 0

        var head1: ListNode? = l1
        var head2: ListNode? = l2

        while (l1 != nil || l2 != nil || carry != 0) {

            val1 = head1 != nil ? head1!.val : 0
            val2 = head2 != nil ? head2!.val : 0

            out = (val1 + val2 + carry) % 10
            carry = (val1 + val2 + carry) / 10

            resultTail.next = ListNode(out)
            resultTail = resultTail.next!

            head1 = head1?.next!
            head2 = head2?.next!

        }
        return result.next!
    }
}
let node3 = ListNode(3)
let node2 = ListNode(4, node3)
let node1 = ListNode(2, node2)

let node3a = ListNode(5)
let node2a = ListNode(6, node3a)
let node1a = ListNode(4, node2a)

let solution = Solution().addTwoNumbers(node1, node1a)

致以最良好的祝愿, Farros

如果您搜索“意外发现零”错误消息,您将找到几个问题和答案,解释这意味着什么,并建议调试技术

虽然此错误的根本原因可能很微妙,但异常的触发因素是强制展开
nil
的可选项或引用隐式展开的
nil
可选项

这里没有太多的代码,所以不难找到在哪里做这些事情

在检查
nil
之后,强制使用三元运算符展开,这样就不会崩溃

您可以强制展开
resultTail.next
result.next
,但在这些情况下您已经指定了值,因此不会导致崩溃

最后一个位置是在while循环的底部强制展开
head1.next
head2.next
。这是一个错误,因为您知道
next
最终将
nil
放在列表的末尾

只需删除
将消除异常,但会引入一个新的错误,因为
while
循环条件会测试初始参数
l1
l2
,它们的值不会改变。你冒着无限循环的风险。我想你是想引用
head1
head2

您应该尝试消除所有强制展开,这并不难:

  • 使用nil聚结运算符而不是三元运算符
  • head1
    head2
    是可选的,因此无需强制展开
    next
  • 您的函数返回一个可选值,因此我们可以将
    resultTail
    声明为可选值,并使用条件展开或不展开
请注意,如果编译器无法自动推断正确的类型,或者您需要与编译器将推断的类型不同的类型,那么您只能显式地键入变量

您还可以通过在单个
init

public class ListNode {
    public var val: Int
    public var next: ListNode?
    public init(val: Int = 0, next: ListNode? = nil) { 
        self.val = val
        self.next = next
    }
}

class Solution {
    func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
        let result = ListNode()
        var resultTail: ListNode? = result
        var carry = 0

        var head1 = l1
        var head2 = l2

        while (head1 != nil || head2 != nil || carry != 0) {

            let val1 = head1?.val ?? 0
            let val2 = head2?.val ?? 0

            let sum = val1 + val2 + carry
            let out = sum % 10
            carry = sum / 10

            resultTail?.next = ListNode(val: out)
            resultTail = resultTail?.next

            head1 = head1?.next
            head2 = head2?.next
        }
        return result.next
    }
}

let node3 = ListNode(val:3)
let node2 = ListNode(val: 4, next: node3)
let node1 = ListNode(val: 2, next: node2)

let node3a = ListNode(val:5)
let node2a = ListNode(val: 6, next: node3a)
let node1a = ListNode(val: 4, next: node2a)

let solution = Solution().addTwoNumbers(node1, node1a)
如果搜索“意外发现零”错误消息,您将找到几个问题和答案,解释这意味着什么,并建议调试技术

虽然此错误的根本原因可能很微妙,但异常的触发因素是强制展开
nil
的可选项或引用隐式展开的
nil
可选项

这里没有太多的代码,所以不难找到在哪里做这些事情

在检查
nil
之后,强制使用三元运算符展开,这样就不会崩溃

您可以强制展开
resultTail.next
result.next
,但在这些情况下您已经指定了值,因此不会导致崩溃

最后一个位置是在while循环的底部强制展开
head1.next
head2.next
。这是一个错误,因为您知道
next
最终将
nil
放在列表的末尾

只需删除
将消除异常,但会引入一个新的错误,因为
while
循环条件会测试初始参数
l1
l2
,它们的值不会改变。你冒着无限循环的风险。我想你是想引用
head1
head2

您应该尝试消除所有强制展开,这并不难:

  • 使用nil聚结运算符而不是三元运算符
  • head1
    head2
    是可选的,因此无需强制展开
    next
  • 您的函数返回一个可选值,因此我们可以将
    resultTail
    声明为可选值,并使用条件展开或不展开
请注意,如果编译器无法自动推断正确的类型,或者您需要与编译器将推断的类型不同的类型,那么您只能显式地键入变量

您还可以通过在单个
init

public class ListNode {
    public var val: Int
    public var next: ListNode?
    public init(val: Int = 0, next: ListNode? = nil) { 
        self.val = val
        self.next = next
    }
}

class Solution {
    func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
        let result = ListNode()
        var resultTail: ListNode? = result
        var carry = 0

        var head1 = l1
        var head2 = l2

        while (head1 != nil || head2 != nil || carry != 0) {

            let val1 = head1?.val ?? 0
            let val2 = head2?.val ?? 0

            let sum = val1 + val2 + carry
            let out = sum % 10
            carry = sum / 10

            resultTail?.next = ListNode(val: out)
            resultTail = resultTail?.next

            head1 = head1?.next
            head2 = head2?.next
        }
        return result.next
    }
}

let node3 = ListNode(val:3)
let node2 = ListNode(val: 4, next: node3)
let node1 = ListNode(val: 2, next: node2)

let node3a = ListNode(val:5)
let node2a = ListNode(val: 6, next: node3a)
let node1a = ListNode(val: 4, next: node2a)

let solution = Solution().addTwoNumbers(node1, node1a)

哪一行给你错误?我们不是来帮你调试的。有很多方法可以调试它。你说你不能单步通过代码,因为你在操场上。那么,为什么不创建一个macOS命令行应用程序,将此代码复制并粘贴到其中,然后添加一些断点呢?现在是学习如何使用Xcode调试器遍历带有一些断点的代码的好时机,并逐步了解它在做什么。您可以在游戏中添加
print()
语句。这会告诉你什么是零。忘了加上一句:清扫者的建议很好。操场不支持断点/调试,但您可以将此代码复制到一个裸项目中,并在那里进行调试。如果您对如何进行调试有任何疑问,请告诉我们哪一行给出了错误?我们不是来为您调试的。有很多方法可以调试它。你说你不能单步通过代码,因为你在操场上。那么,为什么不创建一个macOS命令行应用程序,将此代码复制并粘贴到其中,然后添加一些断点呢?现在是学习如何使用Xcode调试器遍历带有一些断点的代码的好时机,并逐步了解它在做什么。您可以在游戏中添加
print()
语句。那会告诉你什么是零