Mac Catalyst:tableView 允许多重选择不起作用
Posted
技术标签:
【中文标题】Mac Catalyst:tableView 允许多重选择不起作用【英文标题】:Mac Catalyst: tableView allowmultipleselection not working 【发布时间】:2020-07-06 11:00:51 【问题描述】:我有一个允许多选的表格视图。我在 viewDidLoad 中将allowMultipleSelection 和allowsMultipleSelectionDuringEditing 都设置为true,这在ios 和iPadOS 上都能完美运行。我决定今天试用 Catalyst,该应用程序看起来不错,只是我无法在此视图中选择多行。有任何想法吗?这是下面的代码。非常感谢。
//允许多选
override func viewDidLoad()
super.viewDidLoad()
self.tableView.allowsMultipleSelection = true
self.tableView.allowsMultipleSelectionDuringEditing = true
.....
//限制选择为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
【问题讨论】:
【参考方案1】:macOS Catalyst 上的多项选择与在 iOS 和 iPadOS 上的工作方式不同,这似乎是一个错误,或者是对预期行为的不幸选择。
在 macOS Catalyst 上,如果您通过将 tableView.allowsMultipleSelectionDuringEditing 设置为 true 来启用编辑模式下的多选,则一次只能通过指针单击直接选择一行。但是,通过选择第一行然后在选择第二行时按住 SHIFT 来启用连续行的多选,通过选择第一行然后在选择其他行时按住 COMMAND 来启用非连续行的多选。这是类似于 Mac 的行为,因为它是多选通常在 macOS 上的工作方式。因此,这可能是预期的行为。但如果是这样的话,这是难以发现的行为,而不是 iOS/iPadOS 用户可能期望的,并且与 iOS 和 iPadOS 上的工作方式不同。它会导致其他问题 - 例如,在代码中,我有一个“全选”功能,能够从 iOS/iPadOS 上的代码中选择所有行,而此代码在 macOS Catalyst 上不起作用。
我对此提交了反馈。 GitHub 上有一个简单的项目WB2ISS/MultipleSelection 可以演示该问题。
【讨论】:
感谢您提供详细而清晰的答案,您的项目清楚地展示了这种行为。我也不同意这种方法,因为-正如您所说-很难发现,并且用户在他们的设备上的行为应该是一致的。我想唯一的出路是向苹果提交反馈并希望最好!再次感谢。 看起来 Apple 故意选择这种行为以与 macOS 行为保持一致,但是,在撰写本文时绝对没有关于它的文档。我们的应用看起来不像 Mac 应用,它看起来像 iPad 应用(因为 Catalyst)。我的观点是,用户将与应用程序进行交互,就好像它是 iPad 应用程序而不是 Mac 应用程序一样;因此,不会想到 command + click 来执行多选。 嗨 :) 在我的应用程序中,我不需要进入编辑模式,所以我只有tableView.allowsMultipleSelection = true
。这在 iOS 中可以很好地选择一个或多个单元格。但是在不能使用 Shift/Command+click 的 Catalyst 上……有人有幸在这种模式下选择多个单元格吗?谢谢! :)【参考方案2】:
虽然这里所说的一切都是真的,但有一种“简单”的方法可以破解这种行为。使用下面的代码,您将在 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
【讨论】:
感谢分享这个解决方法;对我来说,每个选定的单元格"blinks" 每次选择/取消选择一个新单元格时;这也发生在你身上吗?您找到解决方法了吗? 我也找到了解决方法并相应地编辑了答案。你必须覆盖shouldHighlightRowAt
这是一个很好的解决方法。编辑结束时,我发现有必要删除为减轻闪光/闪烁而添加的高光。此外,当从代码中进行选择时,比如实现全选函数,问题仍然存在,因为.selectRow(at:animated:scrollPosition:)
没有调用willSelectRowAt
或willDeselectRowAt
委托方法。尽管整体多选行为是预期的,但.selectRow(at:animated:scrollPosition:)
的当前行为显然是一个错误。希望它会在 macOS 11 中得到修复。【参考方案3】:
以下是@ph1lb4 提供的解决方案,打包为独立的class
。重要的是,这个版本在选择行时会调用didSelectRowAt
,这意味着依赖于didSelectRowAt
的子类不会中断。
import UIKit
// WORKAROUND:
// As of macOS 10.15 Catalina, multi-row selection in Catalyst apps is not
// intuitive. The user is expected to use the shift key to select multiple
// rows. See https://***.com/q/60856636/1306956 for more details.
open class CatalystWorkaroundTableViewController: UITableViewController
#if targetEnvironment(macCatalyst)
override open func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath?
if let selectedRows = tableView.indexPathsForSelectedRows, selectedRows.contains(indexPath)
tableView.deselectRow(at: indexPath, animated: false)
self.tableView(tableView, didSelectRowAt: indexPath)
return nil
else
return indexPath
override open func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath?
if let selectedRows = tableView.indexPathsForSelectedRows, selectedRows.contains(indexPath)
return nil
else
return indexPath
// WORKAROUND:
// Catalyst de-highlights cells beofre selecting them again which results in flickering.
override open func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool
for indexPath in tableView.indexPathsForSelectedRows ?? []
tableView.cellForRow(at: indexPath)?.isHighlighted = true
return true
#endif
【讨论】:
【参考方案4】:好消息!在 macOS Big Sur UITableView tableView.allowsMultipleSelection = true
就像在 iOS 中一样工作!快乐的时光!您还可以通过编程方式选择多个单元格!
【讨论】:
我正在使用 Big Sur,截至 2021 年 9 月,我的 Mac Catalyst 应用程序中仍然存在 OP 概述的行为。 @lukemmtt 您是否使用 Command 键来选择更多?还有范围的Shift键?我这里没有我的应用,所以我现在不能自己尝试,抱歉。 command 键和 shift 键工作得非常好——但我和大多数用户都不会想到为像我这样使用 iPad 习语的 Mac Catalyst 应用程序这样做(即不是“为 mac 优化” )。这里的其他答案一致认为,这种行为要么是错误,要么是 Apple 的错误决定。在将我的 iPad 应用程序移植到 Mac Catalyst 时,我希望所有用户交互都保持不变,因为它们看起来几乎相同。最终,我在上面实现了 Rudolf Adamkovič 的基于类的解决方案,它在恢复预期的用户体验方面很有魅力——点击选择/取消选择。 好的,我明白了。我的评论是它完全被破坏了,但后来它开始在大苏尔工作。我认为它是否符合 iPad 体验是另一个讨论:)【参考方案5】:下面是objective-c中写的解决方案。
谢谢。 @ph1lb4
#if TARGET_OS_MACCATALYST
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
NSArray<NSIndexPath *> * selectedRows = [tableView indexPathsForSelectedRows];
if ([selectedRows containsObject:indexPath])
[tableView deselectRowAtIndexPath:indexPath animated:false];
return nil;
return indexPath;
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath
NSArray<NSIndexPath *> * selectedRows = [tableView indexPathsForSelectedRows];
if ([selectedRows containsObject:indexPath])
return nil;
return indexPath;
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
NSArray<NSIndexPath *> * selectedRows = [tableView indexPathsForSelectedRows];
for(NSIndexPath *index in selectedRows)
[[tableView cellForRowAtIndexPath:index] setHighlighted:YES];
return YES;
#else
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
return indexPath;
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath
return indexPath;
#endif
【讨论】:
以上是关于Mac Catalyst:tableView 允许多重选择不起作用的主要内容,如果未能解决你的问题,请参考以下文章
为啥我不能在 Mac Catalyst 上创建 AVAudioFile? (错误-54)
如何在 Mac 上的 Mac Catalyst 应用程序中使用钥匙串?
UIMarkupTextPrintFormatter 和 Mac Catalyst