ios - 获取数组中的可选值

标签 ios swift uitableview

给定一个类型为 Book 的可选数组,在 TableView Controller 类中声明:

var books: [Book]?

稍后在 cellForRowAtIndexPath 中我有:

    let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath)

    let book = books?[indexPath.row]

     cell.textLabel?.text = book?.title

    return cell
}

现在,到目前为止,我只看到这本书数组可选地使用 if let 语句展开以循环遍历数组。 但是为什么在这里的 cellForRow 中我们不打开书籍并打开书籍而不是添加另一本书?在它之后,如 books?[indexPath.row]cell.textLabel?.text = book?.title

最佳答案

您不必打开 booksbook因为text UILabel 的属性(property)是可选的 String? .唯一需要解包可选值的情况是,如果您在某些不接受可选值的上下文中使用检索到的值。但是text确实如此,所以您的示例运行良好。

我对这种语法的问题是,虽然它是一种有用的速记,但有点草率。如果存在编程问题(例如,booksnil,即使在技术上不应该调用它时),问题中的代码将默默地继续执行,您将挠头,想知道为什么单元格中的标签是空白的。 (对于建议使用 guard 语句的模式也是如此,如果解包失败则悄悄返回 cell。)

但我强烈反对其他地方提供的建议 books不应该是可选的。如果在实例化 View Controller 时无法填充此数组,则 books 应该 是可选的(并且是 nil )直到检索到此信息。

最重要的是,“books 尚未设置”和“books 已填充,但未返回任何记录”之间存在差异。这是可选值的目的,以避免像“空数组”这样的任意标记值来指示 books。没有设置其值。 (我同情那些反对草率地过度使用可选值的人,但这根本不是其中之一。而且我也不相信 Optional 性能开销问题,因为它在这个例子中并不重要而且它我觉得这是过早优化的完美例子。)

相反,我认为您应该 (a) 离开 books选修的;但是(b)检测它是否意外nil并将其报告为错误,因为如果 cellForRowAt被调用,它不能是nil .

因此,我建议:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "BookCell", for: indexPath)

    let book = books![indexPath.row]

    cell.textLabel?.text = book.title

    return cell
}

这完成了我们想要的,正确填充标签,但如果存在代码逻辑错误和books,也会立即将开发人员带到有问题的代码行。是nil .

现在,许多开发人员非常厌恶使用 !强制解包运算符。我个人认为这很好,因为如果 books 是一个基本的编程错误是nil当此方法被调用时,强制解包运算符将在违规行停止我的执行,我将准确地知道问题是什么。

但是,如果你真的想避免强制展开运算符,! , 然后使用 guard声明,触发信息 fatalError如果booksnil :

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "BookCell", for: indexPath)

    guard let book = books?[indexPath.row] else {
        fatalError("No book found")
    }

    cell.textLabel?.text = book?.title

    return cell
}

关键是如果出现books的情况是nil ,您想在开发过程中立即知道,而不是猜测问题的根源。

需要说明的是,这是强制解包和/或 fatalError模式应该永远用于解包可能因您无法控制的原因而失败的情况。例如,在解析来自远程 Web 服务的响应或处理用户输入时不要使用这些模式。您希望优雅地处理可能导致您无法控制的错误。但是,如果发生特定场景的真正程序错误,则强制解包和/或 fatalError方法是可取的,这样逻辑错误就会立即显现出来,而不是强制您四处寻找异常应用行为的来源。

关于ios - 获取数组中的可选值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46612844/

相关文章:

ios - NSFetchedController 和部分

swift - Swift 中带有 RSS 提要数据源的 TableView 中的图像加载滞后

ios - Swift:xib文件的继承

iOS 键盘在静态表格 View 单元格中覆盖了一些 UITextField

ios - 将非常大的图像缩小为 MTLTexture

iphone - 将光标移动到提交消息的 Xcode 4 快捷方式是什么

objective-c - iOS:我如何知道一个属性是否符合 KVO 标准?

ios - UILabel 在 iPhone 旋转时恢复为默认文本

swift - iBeacon:用于指纹位置估计的粒子滤波器扩展

iphone - 标准 UITableVIewcell UILabel 和 UITextField 中使用的字体是什么?