Why does Swift UITableViewController template use

2020-06-07 04:20发布

问题:

If you create new UITableViewController class, you will see commented method for override:

/*
override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
    let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)

    // Configure the cell...

    return cell
}
*/

You can uncomment method and it will not work because of error

'UITableView?' does not have a member named 'dequeueReusableCellWithIdentifier'

The reason is: tableView is defined as optional type "UITableView?" and you have to unwrap tableView before call the method. For example like this:

let cell = tableView!.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)

But we can make them implicitly unwrapped optionals and use tableView without !

override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
    return cell
}

The question is: why does the xcode define them as optionals? Does it have any reason or advatages vs implicitly unwrapped optionals? Can be we sure, that this method always gets not-nill values?

Also we will have another errors

Constant 'cell' inferred to have type 'AnyObject!', which may be unexpected
Type 'AnyObject!' cannot be implicitly downcast to 'UITableViewCell'; did you mean to use 'as' to force downcast?

We can fix it by adding as UITableViewCell to the end like this:

let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as UITableViewCell

I have no idea why doesn't template look like this by default:

/*
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as UITableViewCell //or your custom class

    // Configure the cell...

    return cell
}
*/

回答1:

Yes, it's weird. In fact, if you erase the template provided methods and start typing each of them, Xcode autocompletion will suggest methods with implicitly unwrapped optional arguments such as

tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!

I guess the templates are currently wrong and might be fixed later, given the fact the template versions aren't even suggested when typing by hand. If you leave them there, they do get called normally though, and it will work as long as you correctly unwrap the parameters as needed.

See this question for more on the discussion.



回答2:

Actually this is the correct way to use the delegate method.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("CELL_ID", forIndexPath: indexPath)
    cell.textLabel.text = "aaaa"
    return cell

}