给定一个类型为 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
最佳答案
您不必打开 books
或 book
因为text
UILabel
的属性(property)是可选的 String?
.唯一需要解包可选值的情况是,如果您在某些不接受可选值的上下文中使用检索到的值。但是text
确实如此,所以您的示例运行良好。
我对这种语法的问题是,虽然它是一种有用的速记,但有点草率。如果存在编程问题(例如,books
是 nil
,即使在技术上不应该调用它时),问题中的代码将默默地继续执行,您将挠头,想知道为什么单元格中的标签是空白的。 (对于建议使用 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
如果books
是nil
:
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/