对swift中的可选类型感到困惑(“Nil可以与Int比较”)

时间:2015-12-29 15:46:36

标签: swift2

我忘了将tableView连接到Interface Builder中的ViewController, 所以变量tableView现在为零。

我对可选类型感到困惑。看看下面的代码

class ViewController: NSViewController {

    @IBOutlet weak var tableView: NSTableView?

     override func viewDidLoad() {

           super.viewDidLoad()

           if self.tableView?.selectedRow != 0 {
              print("do something")
           }
    }
}

当我的实例的可选变量if为零时,为什么我的tableView语句为真?

在Swift中,“nil可以与Int比较吗?”这是否有意义?

2 个答案:

答案 0 :(得分:4)

因为声明

nil != 0 // true !!!

永远是真的

if self.tableView?.selectedRow != nil {
    print("do something")
}

可能,你想要什么。甚至更好..

if let selectedRow = self.tableView?.selectedRow {
    print(selectedRow)
}

因为它不够富有表现力,我在苹果文档中添加了引文

  

“Swift的nil与Objective-C中的nil不同。在Objective-C中,   nil是指向不存在的对象的指针。在Swift中,nil不是   指针 - 它缺少某种类型的值。可选项   任何类型都可以设置为nil,而不仅仅是对象类型。“

摘自:Apple Inc.“Swift编程语言(Swift 2.2)。”iBooks。

"那么,将nil与Int"进行比较是否有意义?

为什么编译器不会抱怨nil和非可选值的比较?

let i: Int? = 2
i == 2    // true
i == 0    // false
i == nil  // false

let s: String? = "str"
s == "str" // true
s == nil   // false

let j: Int! = nil
j == nil   // true

let k: Int? = nil
k == nil   // true

以上所有内容必须是有效使用Swift的可选项概念的有效陈述

答案 1 :(得分:1)

编辑更新:在OP 添加其他问题后)

我会在你的问题中添加一个答案

  

"它是否有意义" nil可以与Int"在斯威夫特?"

您可以将Optional类型视为Int或加倍Double,并使用(简化的)枚举实现

enum Optional<T> {
    case None
    case Some(T)

    init(_ value: T) {
        self = .Some(value)
    }

    init() {
        self = .None
    }
}

T类型中的通用Optional从未用于案例.None,在此讨论中,nilInt?。因此,任何可选的类型(例如String?nil等)都可以与nil进行比较。为了便于讨论,您几乎可以将nil视为单个文字,可用于初始化或为任何定义为可选的类型赋值。对于后一种说法,很明显我们也可以将可选类型的值与nil进行比较。

因此:是的,我们可以将任何可选变量的??进行比较,但通常有更好的选项,例如可选链接或零合并运算符(if a.b?.c != d { ...)。

编辑之前,仍然相关

我将添加一个示例,以帮助向您展示构造为struct MyStruct { var myRow : Int init (row: Int) { myRow = row } } struct MyTopStruct { var myStruct : MyStruct? = nil mutating func setValueToMyStruct(row: Int) { myStruct = MyStruct(row: row) } } 的循环中的内容。

考虑以下结构:

a

MyTopStruct成为var a = MyTopStruct() let myInt = 10 var myOptionalInt : Int? = nil 的实例,并在我们的示例中包含一些整数和可选的整数属性:

if a.b?.c != d { ...

然后,我们对nil子句有一些不同的结果,具体取决于此示例中的选项是否为/* "a.myStruct?" returns nil, and this clause will hence compare "nil != myInt"?, which will always be true, since myInt is a non-optional integer */ if a.myStruct?.myRow != myInt { print("Entered 1") // prints } /* "a.myStruct?" still nil, and myOptionalInt not yet initialised so also nil. Hence, "nil != nil"? => false */ if a.myStruct?.myRow != myOptionalInt { print("Entered 2") // doesnt print } /* now initialise a.myStruct */ a.setValueToMyStruct(myInt) /* "a.myStruct?" now returs value of myInt (10), which != nil, the latter being the current value of myOptionalInt => always enters */ if a.myStruct?.myRow != myOptionalInt { print("Entered 3") // prints } /* finally initialize myOptionalInt */ myOptionalInt = 9 /* Now this is the first comparison that can actually behave in "different ways" w.r.t. how we usually think of if clauses: comparing _values_ of same-type objects. Hence, comparison now depends on the two non-nil values of a.myStruct?.myRow and myOptionalInt */ if a.myStruct?.myRow != myOptionalInt { print("Entered 4") // prints, since 10 != 9 } (已初始化)。

<code>
Please go through the following steps to display the select list as year links 
//hook_theme
function mymodule_theme($existing, $type, $theme, $path){
    return array(
        'list_items' => array(
            'template' => 'list_items', //tpl to display them as list
            'path' => $path . '/templates', 
            'type' => 'module',
            'variables' => array(
                'list' => NULL,
                'current' => NULL
            ),
        ),
    );
}
/*
hook_form_alter
*/
function mymodule_form_alter(&$form, &$form_state, $form_id) {
    if($form_id == 'views_exposed_form') {
     $current = '';
     $ranges = explode(':',$form['date_filter']['value']['#date_year_range']);
    foreach($ranges as $key => $range) {
       $ranges[$key] = date('Y', strtotime($range.' years', strtotime(date('Y-m-d H:i:s'))));
    }    
    $startYear = $ranges[0];
    $endYear = $ranges[1];    
    if($ranges[0] > $ranges[1]) {
        $endYear = $ranges[0];
        $startYear = $ranges[1];
    }    
    $items = array();
    $endYear = (int)$endYear;
    $startYear = (int)$startYear;
    if(empty($_REQUEST['date_filter']['value']['year'])) {
    $items[] = 'All years';
    } else {
       $items[] = l('All years', current_path(),array('query' => array("date_filter[value][year]" => '')) );
    }
for($i=$endYear; $i>=$startYear; $i--) {
        if($_REQUEST['date_filter']['value']['year'] == $i) {
         $items[$i] = $i;
        } else {
         $items[$i] = l($i, current_path(), array('query' => array("date_filter[value][year]" => $i)));
}         
}
$list = theme('list_items', array('list' => $items, 'current' => $_REQUEST['date_filter']['value']['year']));
       $form['html'] = array(
        '#type' => 'markup',
        '#markup' => $list,
    );
    }
}
/*
templates/list_items.tpl.php
*/
<ol><?php foreach($list as $key => $value) { if($current == $key || empty($current)) { ?><li class="active"><?php print $value; ?></li>
<?php } else { ?>  <li><?php print $value; ?></li>
 <?php } } ?></ol>
//mymodule.info
name = Filters customization
description = Filters customization
version = VERSION
core = 7.x
dependencies[] = date
</code>