如何根据用于两个不同目的的 UITableViewController 中的不同条件设置 UITableView AccessoryType?

How can I set a UITableViewAccessoryType based on different conditions in a UITableViewController used for two different purposes?

我有一个显示举重名称列表的 UITableViewController(想想举重),它用于两种不同的用途。它可以从视图 A 访问到 select 将保存为用户默认值的电梯。它也可以从视图 B 访问到 select 电梯,然后将过滤电梯事件列表。在每种情况下,我都希望相应单元格上有一个复选标记以指示当前默认提升(如果来自视图 A)和相应单元格上的复选标记以指示当前 selected 过滤器(如果来自视图 B) .

我为 table 个单元格创建了一个视图模型:

struct LiftCellViewModel: SelectionsRepresentable {

    let liftName: String!
    let liftsDictionary: [String: String]!

    var text: String {
        return liftName
    }

    var accessoryType: UITableViewCellAccessoryType {
        let defaultLiftUuid = UserDefaults.lift()
        let defaultLiftName = liftsDictionary[defaultLiftUuid]

        if liftName == defaultLiftName {
            return .checkmark
        } else {
            return .none
        }
    }
}

这非常有效,但只能处理其中一种情况(来自视图 A)。因此,为了尝试让它也适用于其他场景(来自视图 B),如果列表被用于 select 过滤器,我将传递一个 bool 并在 switch 语句中使用它来确定设置复选标记的路径:

let liftName: String!
let liftsDictionary: [String: String]!
let selectForFilter: Bool!

var text: String {
    return liftName
}

var accessoryType: UITableViewCellAccessoryType {

    switch selectForFilter {
    case true:
        let filterLiftUuid = UserDefaults.logFilterLiftUuid()
        let filterLiftName = liftsDictionary[filterLiftUuid!]

        if liftName == filterLiftName {
            return .checkmark
            } else {
            return .none
            }
    case false:
        let defaultLiftUuid = UserDefaults.lift()
        let defaultLiftName = liftsDictionary[defaultLiftUuid]

        if liftName == defaultLiftName {
            return .checkmark
        } else {
            return .none
        }
    default:
        return .none
    }
}

此视图用于创建 didSelectRow 中的每个单元格:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cellViewModel: SelectionsRepresentable
    let cell = tableView.dequeueReusableCell(withIdentifier: "liftCell", for: indexPath)
    let lift = viewModel.fetchedResultsController?.object(at: indexPath) as! Lift
    let liftName = lift.liftName

    cellViewModel = LiftCellViewModel(liftName: liftName, liftsDictionary: liftsDictionary, selectForFilter: selectForFilter)

    cell.textLabel?.text = cellViewModel.text
    cell.accessoryType = cellViewModel.accessoryType

    return cell
}

这行得通,但是 switch 语句似乎需要很多代码才能完成如此简单的事情。有没有更快捷的方法来做到这一点?

如果您查看 accessoryType 的定义,实际上唯一的区别是您检索的是哪个 UUID,因此这可以简化为如下所示:

var accessoryType: UITableViewCellAccessoryType {
    let uuid = selectForFilter! ? UserDefaults.logFilterLiftUuid() : UserDefaults.lift()
    return liftName == liftsDictionary[uuid!] ? .checkmark : .none
}

说到 swifty,您可能还想重新考虑对隐式解包可选类型的大量使用,并尽可能使用非可选类型。