Swift 使用函数中指定的守卫和致命错误
Swift using guard and fatal error specified in an function
我使用枚举构建我的 UITableView
单元格:
enum VAXSections: Int
{
case Segmented = 0
case Scrollable = 1
case ScheduledMode = 2
case ScheduledFooter = 3
case SilentHours = 4
case SilentFooter = 5
}
这里是我的使用方法:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
guard let unwrappedSection = VAXSections(rawValue: indexPath.section) else {
showFatalError()
return nil
}
这里没有什么问题我想保护我的节值,如果它在我的枚举中超出最大大小写。例如,如果 indexPath.section 大于 5,那么应用程序应该回退。但是如果你看到我们不能在这里 return nil,因为 cellForRowAtIndexPath
在任何情况下都必须 return 单元格。
我可以通过将 showFatalError() 小说替换为以下内容来提供更多可读性来解决问题:
guard let unwrappedSection = VAXSections(rawValue: indexPath.section) else {
fatalError("Check \(String(VAXUnitDashboardViewController.self)) UITableView datasource or check \(String(VAXSections.self)) enum.")
}
那么我不需要 return 任何值。但后来我又遇到了另一个问题。因为我需要为我的 UITableView
指定至少 3 个数据源函数,所以我需要复制致命错误,我希望将其替换为一个始终执行相同操作的函数:
fatalError("Check \(String(VAXUnitDashboardViewController.self)) UITableView datasource or check \(String(VAXSections.self)) enum.")
我认为您实际上不需要在 3 个地方安装它。假设您正在谈论的 3 种数据源方法是:
func numberOfSectionsInTableView(_ tableView: UITableView) -> Int
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
实际上,您只需要在其中之一上进行保护。
numberOfSectionsInTableView
是第一个调用的方法,所以如果你在这里失败,其他两个方法将不会被调用。如果部分的数量是基于一些计算的,你也可以截断这个值,像这样:if calculatedNumberOfSections > 6 { return 6 } else { return calculatedNumberOfSections }
(记住部分编号是基于0
)
numberOfRowsInSection
- 如果你在这里守卫,你有两个选择 - 要么以 fatalError
失败,要么(我认为更好)- return 0
如果部分编号高于 5
则通过。返回 0
将导致 cellForRowAtIndexPath
不被该部分调用。
cellForRowAtIndexPath
- 你已经知道了:)
enum VAXItems: String {
case Item1
case Item2
case Item3
}
enum VAXSections: String {
case Segmented
case Scrollable
case ScheduledMode
case ScheduledFooter
case SilentHours
case SilentFooter
}
struct VAXModel {
var type: VAXSections
var items: [VAXItems]
}
然后在您的 UIViewController 上您可以拥有:
class ViewController: UIViewController {
private var model: [VAXModel] = []
override func viewDidLoad() {
super.viewDidLoad()
model = [
VAXModel(type: .ScheduledMode, items: [.Item1, .Item2, .Item3]),
VAXModel(type: .SilentFooter, items: [.Item1])
]
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return model.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return model[section].items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(String(UITableViewCell), forIndexPath: indexPath)
let item = model[indexPath.section].items[indexPath.row]
switch item {
case .Item1: cell.textLabel?.text = item.rawValue
case .Item2: // Config
case .Item3: // Config
}
return cell
}
}
我使用枚举构建我的 UITableView
单元格:
enum VAXSections: Int
{
case Segmented = 0
case Scrollable = 1
case ScheduledMode = 2
case ScheduledFooter = 3
case SilentHours = 4
case SilentFooter = 5
}
这里是我的使用方法:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
guard let unwrappedSection = VAXSections(rawValue: indexPath.section) else {
showFatalError()
return nil
}
这里没有什么问题我想保护我的节值,如果它在我的枚举中超出最大大小写。例如,如果 indexPath.section 大于 5,那么应用程序应该回退。但是如果你看到我们不能在这里 return nil,因为 cellForRowAtIndexPath
在任何情况下都必须 return 单元格。
我可以通过将 showFatalError() 小说替换为以下内容来提供更多可读性来解决问题:
guard let unwrappedSection = VAXSections(rawValue: indexPath.section) else {
fatalError("Check \(String(VAXUnitDashboardViewController.self)) UITableView datasource or check \(String(VAXSections.self)) enum.")
}
那么我不需要 return 任何值。但后来我又遇到了另一个问题。因为我需要为我的 UITableView
指定至少 3 个数据源函数,所以我需要复制致命错误,我希望将其替换为一个始终执行相同操作的函数:
fatalError("Check \(String(VAXUnitDashboardViewController.self)) UITableView datasource or check \(String(VAXSections.self)) enum.")
我认为您实际上不需要在 3 个地方安装它。假设您正在谈论的 3 种数据源方法是:
func numberOfSectionsInTableView(_ tableView: UITableView) -> Int
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
实际上,您只需要在其中之一上进行保护。
numberOfSectionsInTableView
是第一个调用的方法,所以如果你在这里失败,其他两个方法将不会被调用。如果部分的数量是基于一些计算的,你也可以截断这个值,像这样:if calculatedNumberOfSections > 6 { return 6 } else { return calculatedNumberOfSections }
(记住部分编号是基于0
)numberOfRowsInSection
- 如果你在这里守卫,你有两个选择 - 要么以fatalError
失败,要么(我认为更好)- return0
如果部分编号高于5
则通过。返回0
将导致cellForRowAtIndexPath
不被该部分调用。cellForRowAtIndexPath
- 你已经知道了:)
enum VAXItems: String {
case Item1
case Item2
case Item3
}
enum VAXSections: String {
case Segmented
case Scrollable
case ScheduledMode
case ScheduledFooter
case SilentHours
case SilentFooter
}
struct VAXModel {
var type: VAXSections
var items: [VAXItems]
}
然后在您的 UIViewController 上您可以拥有:
class ViewController: UIViewController {
private var model: [VAXModel] = []
override func viewDidLoad() {
super.viewDidLoad()
model = [
VAXModel(type: .ScheduledMode, items: [.Item1, .Item2, .Item3]),
VAXModel(type: .SilentFooter, items: [.Item1])
]
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return model.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return model[section].items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(String(UITableViewCell), forIndexPath: indexPath)
let item = model[indexPath.section].items[indexPath.row]
switch item {
case .Item1: cell.textLabel?.text = item.rawValue
case .Item2: // Config
case .Item3: // Config
}
return cell
}
}