2015-09-08 3 views
2

Я тренирую Swift, создавая деревья с массивом.Swift: Как сравнить Необязательно в разделе «if»

У меня есть класс Node. Каждый узел имеет идентификатор и родительский идентификатор. Идентификатор родительского элемента может быть равен нулю, если узел является узлом верхнего уровня. Поэтому я сделал родительский идентификатор Необязательным.

Затем я вручную (для целей тестирования) создал массив узлов, который содержит несколько деревьев. Таким образом, существует несколько узлов с родительским ID = nil.

Затем я создал функцию, которая находит узлы по их родительскому идентификатору.

Компилятор не жаловался. Однако при запуске в iPhone симулятор (я пытался отобразить узлы в Tableview), появится сообщение в статье, если в функции:

fatal error: unexpectedly found nil while unwrapping an Optional value

Пожалуйста, помогите. Благодарю.

Вот код. (для моей привычки я пишу «» в конце каждой строки.)

class Node { 
    var id:Int; 
    var parent:Int!; 
    init(id:Int, parent:Int!) { 
    self.id = id; 
    self.parent = parent; 
    } 
} 

var allNodes = [ 
    Node(id:1, parent: nil), 
    Node(id:2, parent: nil), 
    Node(id:3, parent: 1), 
    Node(id:4, parent: 1), 
    Node(id:5, parent: 2), 
    Node(id:6, parent: 2), 
    Node(id:7, parent: 2) 
]; 

func findNodes(parent:Int!) -> [Node] { 
    var arr:[Node] = []; 
    for node in allNodes { 
    if node.parent == parent! { 
     // if I use "if node.parent == parent" without the "!" it gives me the same error 
     arr.append(node); 
    } 
    } 
    return arr; 
} 

let nodes = self.findNodes(nil); 
// called in tableview functions. 
// same message if I use findNodes(1). 

ответ

4

Ваша функция находки объявлена ​​как

func findNodes(parent:Int!) -> [Node] 

где параметр объявлен как неявно развернутым по желанию, поэтому он будет разворачиваться при каждом доступе. Если вы хотите передать nil в качестве параметра, то «нормальный» необязательно имеет смысл:

func findNodes(parent:Int?) -> [Node] { 
    var arr:[Node] = []; 
    for node in allNodes { 
     if node.parent == parent { 
      arr.append(node); 
     } 
    } 
    return arr; 
} 

Обратите внимание, что вы можете упростить код (Swift 1.2):

func findNodes(parent:Int?) -> [Node] { 
    return filter(allNodes) { $0.parent == parent }; 
} 

Он также будет больше смысла объявить parent свойство в Node классе как опция, если nil является «ожидаемым» значение:

class Node { 
    var id : Int; 
    var parent : Int?; 
    init(id:Int, parent : Int?) { 
     self.id = id; 
     self.parent = parent; 
    } 
} 

Или, возможно (дополнительно) указатель на родительский узел:

var parent : Node? 

но теперь не связан с вашим вопросом.

+0

Спасибо, Мартин Р, это работает для меня! Я новичок в Swift. Сначала я сделал это неявным образом развернутым, потому что я думал, что это облегчит каждый раз, когда я его получу. Позвольте мне задать еще один глупый вопрос: означает ли это, что опция может быть нулевой и неявно развернутой. Необязательно не должно быть nil? – golddc

+0

И да, я хотел использовать ваш последний совет «var parent: Node?», Но потом выяснилось, что я не знаю, как его хранить в базе данных, если в какой-то момент мне нужно, поэтому я сдался и использовал Int ID вместо ... – golddc

+1

@golddc: посмотрите на http://stackoverflow.com/questions/24006975/why-create-implicitly-unwrapped-optionals для возможных вариантов использования неявно развернутых опций. –

Смежные вопросы