Mac Catalyst:tableView 允许多选不起作用

oho*_*idi 10 swift mac-catalyst

我有一个允许多选的tableview。我已经在 viewDidLoad 中将 allowedMultipleSelection 和 allowedMultipleSelectionDuringEditing 设置为 true ,这在 iOS 和 iPadOS 上都可以完美运行。我决定今天试用 Catalyst,该应用程序看起来不错,只是我无法在此视图中选择多行。有任何想法吗?这是下面的代码。提前谢谢了。

//允许多选

override func viewDidLoad() 
{
    super.viewDidLoad()

    self.tableView.allowsMultipleSelection = true
    self.tableView.allowsMultipleSelectionDuringEditing = true
.....
}
Run Code Online (Sandbox Code Playgroud)

//限制选择为7行

override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    if let selectedItems = tableView.indexPathsForSelectedRows {

        if selectedItems.count > 6 {
            return nil
        }
    }
    return indexPath
}

@IBAction func doneButtonTapped(_ sender: UIBarButtonItem) {

...

    let selectedIndexPaths = tableView.indexPathsForSelectedRows
    if !selectedIndexPaths!.isEmpty {
        for index in selectedIndexPaths! {
            let selectedProcedure = fetchedResultsController?.object(at: index) as! Item
...

Rest of code to perform the required task
}
Run Code Online (Sandbox Code Playgroud)

WB2*_*ISS 13

macOS Catalyst 上的多项选择与 iOS 和 iPadOS 上的工作方式不同,这似乎是一个错误,或者是对预期行为的不幸选择。

在 macOS Catalyst 上,如果您通过将 tableView.allowsMultipleSelectionDuringEditing 设置为 true 来启用编辑模式下的多选,则一次只能通过指针单击直接选择一行。但是,通过选择第一行然后在选择第二行的同时按住 SHIFT 来启用连续行的多选,通过选择第一行然后在选择其他行的同时按住 COMMAND 来启用非连续行的多选。这是类似于 Mac 的行为,因为它是多选通常在 macOS 上工作的方式。所以这可能是有意的行为。但如果是这种情况,则是难以发现的行为,而不是 iOS/iPadOS 用户可能期望的行为,并且与 iOS 和 iPadOS 的工作方式不同。它会导致其他问题 - 例如,

我对此提出了反馈意见。GitHub 上的WB2ISS/MultipleSelection有一个简单的项目来演示这个问题。

  • 看起来 Apple 故意选择此行为以与 macOS 行为保持一致,但是,截至撰写本文时,还没有任何相关文档。我们的应用程序看起来不像 Mac 应用程序,它看起来像 iPad 应用程序(因为 Catalyst)。我的观点是,用户将与该应用程序进行交互,就像它是 iPad 应用程序而不是 Mac 应用程序一样;因此,不会想到命令+单击来执行多重选择。 (3认同)

ph1*_*lb4 9

虽然这里所说的一切都是真的,但有一种“简单”的方法可以破解这种行为。使用下面的代码,您将在 Mac 上获得与在 iOS/iPadOS 上相同的行为

#if targetEnvironment(macCatalyst)
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    if let selectedRows = tableView.indexPathsForSelectedRows, selectedRows.contains(indexPath) {
        tableView.deselectRow(at: indexPath, animated: false)
        return nil
    }
    return indexPath
}

func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? {
    if let selectedRows = tableView.indexPathsForSelectedRows, selectedRows.contains(indexPath) {
        return nil
    }
    return indexPath
}

func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
    // the mac sets isHighlighted of each other cell to false before selecting them again which leads to a flickering of the selection. Therefore go through the selected cells and highlight them here manually
    tableView.indexPathsForSelectedRows?.forEach { tableView.cellForRow(at: $0)?.isHighlighted = true }
    return true
}
#endif
Run Code Online (Sandbox Code Playgroud)