简体   繁体   English

Mac Catalyst:tableView allowmultipleselection 不工作

[英]Mac Catalyst: tableView allowmultipleselection not working

I have a tableview that allows multiple selection.我有一个允许多项选择的表格视图。 I have set both allowsMultipleSelection and allowsMultipleSelectionDuringEditing to true in viewDidLoad and this is working perfectly on both iOS and iPadOS.我在 viewDidLoad 中将 allowsMultipleSelection 和 allowsMultipleSelectionDuringEditing 都设置为 true,这在 iOS 和 iPadOS 上都运行良好。 I have decided to try out the Catalyst today and the app looks good except that I cannot select multiple rows in this view.我决定今天试用 Catalyst,该应用程序看起来不错,只是我不能在此视图中显示 select 多行。 Any ideas?有任何想法吗? Here is the code below.这是下面的代码。 Many thanks in advance.提前谢谢了。

//allow multiple selection //允许多选

override func viewDidLoad() 
{
    super.viewDidLoad()

    self.tableView.allowsMultipleSelection = true
    self.tableView.allowsMultipleSelectionDuringEditing = true
.....
}

//limit selection to 7 rows //将选择限制为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
}

Multiple selection on macOS Catalyst does not work in quite the same way as on iOS and iPadOS and this appears to be either a bug or an unfortunate choice of intended behavior. macOS Catalyst 上的多项选择与 iOS 和 iPadOS 上的工作方式不同,这似乎是一个错误,或者是对预期行为的不幸选择。

On macOS Catalyst, if you have enabled multiple selection in edit mode by setting tableView.allowsMultipleSelectionDuringEditing to true, only one row at a time can be directly selected by clicking with the pointer.在 macOS Catalyst 上,如果您通过将 tableView.allowsMultipleSelectionDuringEditing 设置为 true 来启用编辑模式下的多选,则一次只能通过指针单击直接选择一行。 However, multiple selection of contiguous rows is enabled by selecting a first row and then holding down SHIFT while selecting a second row, and multiple selection of non-contiguous rows is enabled by selecting a first row and then holding down COMMAND while selecting additional rows.但是,通过选择第一行然后在选择第二行的同时按住 SHIFT 来启用连续行的多选,通过选择第一行然后在选择其他行的同时按住 COMMAND 来启用非连续行的多选。 This is Mac-like behavior in that it is how multiple selection generally works on macOS.这是类似于 Mac 的行为,因为它是多选通常在 macOS 上工作的方式。 So it is possible that this was intended behavior.所以这可能是有意的行为。 But if that is the case, it is behavior that is hard to discover, not what an iOS/iPadOS user might expect, and works differently than on iOS and iPadOS.但如果是这种情况,那就是难以发现的行为,而不是 iOS/iPadOS 用户可能期望的行为,并且与 iOS 和 iPadOS 的工作方式不同。 And it causes other problems - for example, in code I have a "Select All" function that is able to select all rows from code on iOS/iPadOS, and this code doesn't work on macOS Catalyst.它会导致其他问题 - 例如,在代码中,我有一个“全选”功能,可以从 iOS/iPadOS 上的代码中选择所有行,而此代码在 macOS Catalyst 上不起作用。

I filed Feedback on this.我对此提出了反馈意见。 There is a simple project on GitHub at WB2ISS/MultipleSelection that demonstrates the problem. GitHub 上的WB2ISS/MultipleSelection有一个简单的项目来演示这个问题。

While everything that was said here is true, there is an 'easy' way to hack this behaviour.虽然这里所说的一切都是真的,但有一种“简单”的方法可以破解这种行为。 With the code below you will get the same behaviour on Mac as on iOS/iPadOS使用下面的代码,您将在 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

Below is the solution provided by @ph1lb4 packaged as a standalone class .以下是@ph1lb4 提供的打包为独立class的解决方案。 Importantly, this version calls didSelectRowAt when selecting rows which means that the subclasses relying on didSelectRowAt will not break.重要的是,此版本在选择行时调用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://stackoverflow.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
}

Great news!好消息! In macOS Big Sur UITableView tableView.allowsMultipleSelection = true works just like in iOS!在 macOS Big Sur UITableView 中tableView.allowsMultipleSelection = true就像在 iOS 中一样工作! Happy days!快乐的时光! You can also a select multiple cells programmatically!您还可以以编程方式选择多个单元格!

Bellow is the solution wrriten in objective-c. Bellow是objective-c中写的解决方案。

Thank you.谢谢你。 @ph1lb4 @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

I had the same problem but with UICollectionView on Catalyst.我有同样的问题,但在 Catalyst 上有 UICollectionView。 I couldn't implement this same solution as UICollectionView is missing some of the delegate functions.我无法实施相同的解决方案,因为 UICollectionView 缺少一些委托函数。 I found this gist that solved it for me.我发现这个要点为我解决了。 https://gist.github.com/stefanceriu/5ff0c67e98ae44612857cd17fd4377d1 https://gist.github.com/stefanceriu/5ff0c67e98ae44612857cd17fd4377d1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM