【问题标题】:Xcode tableview how to select ONE row in EACH sectionXcode tableview如何在每个部分中选择一行
【发布时间】:2013-01-11 06:39:15
【问题描述】:

我有一个包含 2 个部分的表格视图。我希望每个部分只选择一行。现在我可以选择一行,但它适用于整个表格。最终,我希望选择 2 行,但每个 SECTION 只能选择 1 行。我已经坚持了好几天了,无法弄清楚。这可能吗??我是 Xcode 的新手,所以非常感谢任何帮助。提前致谢!

这是我的代码:

//  OptionsViewController.h

#import <UIKit/UIKit.h>

@interface OptionsViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
    NSArray *themeDataArray;
    NSArray *levelDataArray;
    NSIndexPath *selectedRowIndex;
}

@property (weak, nonatomic) NSArray *themeDataArray;
@property (weak, nonatomic) NSArray *levelDataArray;
@property (weak, nonatomic) NSIndexPath *selectedRowIndex;
@property (weak, nonatomic) IBOutlet UITableView *tableView;

@end


//  OptionsViewController.m

#import "OptionsViewController.h"
@interface OptionsViewController ()
@end

@implementation OptionsViewController

- (void)viewDidLoad
{
    themeDataArray = [[NSArray alloc] initWithObjects:@"Classic",@"Animals",@"Dinosaurs",@"Cars", nil];
    levelDataArray = [[NSArray alloc] initWithObjects:@"Easy",@"Medium",@"Hard", nil];

    //set default rows on startup
    NSIndexPath *indexPath=[NSIndexPath indexPathForRow:0 inSection:0];
    [self.tableView selectRowAtIndexPath:indexPath animated:YES  scrollPosition:UITableViewScrollPositionTop];

    NSIndexPath *indexPath2=[NSIndexPath indexPathForRow:0 inSection:1];
    [self.tableView selectRowAtIndexPath:indexPath2 animated:YES  scrollPosition:UITableViewScrollPositionNone];

    [super viewDidLoad];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection (NSInteger)section
{
    //For each section, return header label
    if(section == 0) return @"Themes";
    if(section == 1) return @"Difficulty Level";
    return nil;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    //For each section, return number of rows in section
    if(section == 0) return [themeDataArray count];
    if(section == 1) return [levelDataArray count];
    return 0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell1 = nil;

    //recycles cells to save memory
    cell1 = [tableView dequeueReusableCellWithIdentifier:@"cell1"];

    if (cell1 == nil)
    {
        cell1 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell1"];
    }

    cell1.textLabel.text=[themeDataArray objectAtIndex:indexPath.row];
    return cell1;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView reloadData];
    switch (indexPath.section)
    {
        case 0:
        {
            if (self.selectedRowIndex)
            {
                UITableViewCell *deselectCell = [tableView cellForRowAtIndexPath:self.selectedRowIndex];
                deselectCell.highlighted = FALSE;
                [tableView reloadData];
            }

            //select new row and assign new indexPath
            UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
            newCell.highlighted = TRUE;

            self.selectedRowIndex = indexPath;
            break;
        }
        case 1:
        {
            if (self.selectedRowIndex)
            {
                UITableViewCell *deselectCell = [tableView cellForRowAtIndexPath:self.selectedRowIndex];
                deselectCell.highlighted = FALSE;
            }

            //select new row and assign new indexPath
            UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
            newCell.highlighted = TRUE;

            self.selectedRowIndex = indexPath;
            break;
        }
        default:
            break;
    }
}

@end

【问题讨论】:

    标签: xcode tableview


    【解决方案1】:

    我认为这是上面答案的更 Swifty 风格的代码。

    func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        tableView.indexPathsForSelectedRows?
            .filter { $0.section == indexPath.section }
            .forEach { tableView.deselectRow(at: $0, animated: true) }
        return indexPath
    }
    

    【讨论】:

      【解决方案2】:

      这是上面 John Sauer 的答案的 Swift 3 等价物(以防其他人像我一样偶然发现这个问题):

      func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
          if let selectedIndexPaths = tableView.indexPathsForSelectedRows {
              for selectedIndexPath in selectedIndexPaths {
                  if selectedIndexPath.section == indexPath.section {
                      tableView.deselectRow(at: selectedIndexPath, animated: true)
                  }
              }
          }
          return indexPath
      }
      

      【讨论】:

      • 别忘了设置tableView.allowsMultipleSelection = true
      • 你也可以去掉外部的if let,用tableView.indexPathsForSelectedRows ?? []替换for循环迭代器。
      【解决方案3】:

      那么,您希望在每个部分中一次选择的行不超过 1 行吗?然后一个解决方案是,每当用户触摸一行时,取消选择同一部分中的任何选定行。

      - (NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath {
          for ( NSIndexPath* selectedIndexPath in tableView.indexPathsForSelectedRows ) {
              if ( selectedIndexPath.section == indexPath.section )
                  [tableView deselectRowAtIndexPath:selectedIndexPath animated:NO] ;
          }
          return indexPath ;
      }
      

      【讨论】:

      • 哇,这正是我想要的,谢谢!我完全想多了
      • 这很好用,但我发现这种方法的唯一问题是用户可以通过点击它来取消选择一行,而没有选择任何内容。只需添加以下内容即可防止这种情况发生:-(NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath { return nil; }
      • @JoGoFo 它仍然有取消选择选定单元格的警告,但不会触发didSelectRowAtIndexPath。要绕过它,您可以改为采用tableView:didDeselectRowAtIndexPath: 并手动调用数据源方法tableView:didSelectRowAtIndexPath:
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      • 1970-01-01
      • 2014-10-14
      • 1970-01-01
      • 1970-01-01
      • 2010-12-23
      • 2017-02-26
      相关资源
      最近更新 更多