Ios 具有行展开和折叠选项的tableview的最佳方法

Ios 具有行展开和折叠选项的tableview的最佳方法,ios,objective-c,uitableview,tableview,customization,Ios,Objective C,Uitableview,Tableview,Customization,我有一个包含tableview和searchbar的视图。当我开始搜索时,它应该搜索tableview。以下是附图中tableview的示例数据: 学生1、学生2是表中的不同部分 假设我搜索“S”,那么结果应该如下图所示,其中匹配的行应该可见,不匹配的行应该隐藏,并且“ShowRemaining”按钮应该可见。当我点击“显示剩余”按钮时,它应该显示相同部分的剩余行: 如何实现这一点,如果可能,请提供上述场景的示例。有许多用于展开和折叠表的示例 您可以参考下面的示例 通过在plist文件中动态

我有一个包含tableview和searchbar的视图。当我开始搜索时,它应该搜索tableview。以下是附图中tableview的示例数据:

学生1、学生2是表中的不同部分

假设我搜索“S”,那么结果应该如下图所示,其中匹配的行应该可见,不匹配的行应该隐藏,并且“ShowRemaining”按钮应该可见。当我点击“显示剩余”按钮时,它应该显示相同部分的剩余行:


如何实现这一点,如果可能,请提供上述场景的示例。

有许多用于展开和折叠表的示例

您可以参考下面的示例

通过在plist文件中动态设置。您可以维护可展开和可折叠的tableview

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let currentCellDescriptor = getCellDescriptorForIndexPath(indexPath)
    let cell = tableView.dequeueReusableCellWithIdentifier(currentCellDescriptor["cellIdentifier"] as! String, forIndexPath: indexPath) as! CustomCell

    if currentCellDescriptor["cellIdentifier"] as! String == "idCellNormal" {
        if let primaryTitle = currentCellDescriptor["primaryTitle"] {
            cell.textLabel?.text = primaryTitle as? String
        }

        if let secondaryTitle = currentCellDescriptor["secondaryTitle"] {
            cell.detailTextLabel?.text = secondaryTitle as? String
        }
    }
    else if currentCellDescriptor["cellIdentifier"] as! String == "idCellTextfield" {
        cell.textField.placeholder = currentCellDescriptor["primaryTitle"] as? String
    }
    else if currentCellDescriptor["cellIdentifier"] as! String == "idCellSwitch" {
        cell.lblSwitchLabel.text = currentCellDescriptor["primaryTitle"] as? String

        let value = currentCellDescriptor["value"] as? String
        cell.swMaritalStatus.on = (value == "true") ? true : false
    }
    else if currentCellDescriptor["cellIdentifier"] as! String == "idCellValuePicker" {
        cell.textLabel?.text = currentCellDescriptor["primaryTitle"] as? String
    }
    else if currentCellDescriptor["cellIdentifier"] as! String == "idCellSlider" {
        let value = currentCellDescriptor["value"] as! String
        cell.slExperienceLevel.value = (value as NSString).floatValue
    }

    return cell
}

对于UITableView中的崩溃/扩展行为,我想不出任何通用的“最佳方法”。我怀疑这就是为什么苹果没有提供这种服务的原因。相反,他们给了我们足够的工具,以我们希望的方式实施它

在你的特殊情况下,我有下一个愿景。 我不知道,也不需要知道,您是如何处理任务的模型端的,下面的代码仅用于此答案的目的,即-为您提供所寻求的崩溃行为

我建议以这种方式实施你所期望的行为。在ViewController中,可以控制搜索栏和表视图添加字段

@property NSArray* filteredStudents;
@property NSMutableIndexSet* expandedStudents;
当不进行搜索时,这些属性将为nil(或空实例)。一旦搜索开始(输入第一个符号或点击“搜索”按钮-无论您最喜欢什么)-实例化它们

filteredStudents
-包含对满足搜索条件的学生的引用的数组。它在每次执行搜索时都会更新。每次更新时,执行[tableView reloadData]

expandedStudents
-索引集,告诉您用户在哪些部分按了“全部显示”。别忘了,它只保存章节号。因此,当
filteredStudents
数组更改时,您必须手动更新它。例如,当您输入“S”时,将显示两名学生。在第二个学生身上按Show All
expandStudents
现在有编号
1
。然后输入“Se”,只剩下第二个学生。在这种情况下,您必须将
expandedStudents
中的
1
替换为
0
,因为第二个学生的部分变为第一个

另一个属性

 @property BOOL searchMode;
无论何时显示过滤结果,此属性都应为“是”。不,否则

接下来,像这样修改UITableViewDataSource和委托方法

- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
    if(searchMode) {
       return self.filteredStudents.count;
    }
    else {
       //Your current behaviour here
    }
}

- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if(searchMode) {
       if([self.expandedStudents containsIndex:section]) { // Button "Show all" was already tapped for this student
          return /* Number of all fields you need to show for student. Just like you do now. It is for expanded section */
       }
       else {
           return /* Number of fields that satisfy search criteria for student self.filteredStudents[section] */
       }
    }
    else {
       //Your current behaviour here
    }
}

- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if(searchMode) {
        if(![self.expandedStudents containsIndex:section] && /* indexPath corresponds to place, where "Show All" should be */) {
           //Create "Show All" cell
        }
        else {
          //Create cell that contains info from filtered student fields
        }
    }
    else {
       //Your current behaviour here
    }
}

- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
   if(searchMode && ![self.expandedStudents containsIndex:section] && /* indexPath corresponds to place, where "Show All" should be */) {
      //"Show All" button pressed
      [self.expandedStudents addIndex:indexPath.section];

      [tableView beginUpdates];
      /* For each row, that wasn't presented in collapsed student perform insertRowsAtIndexPaths:withRowAnimation: method */
      [tableView endUpdates];
   }
   else {
      //Your current behaviour
   }
}

我已经为你的要求创建了代码,请找到下面的url下载代码并查看

链接:

环境:Xcode 8和Objective-C

突出显示我完成的代码。

我已经根据您的结构创建了NSObject of student,创建了两个(StudentListCell和ShowMoreCell)
UITableViewCell
用于显示学生记录和“显示剩余按钮”记录

我还使用了两个(arrStudentInfo,arrSearchInfo)
NSMutablebleArray
来保存搜索记录和原始记录

之后,我在
ViewController.m
中初始化student的NSObject。请查找下面的代码

- (void)setupData {

    self.arrStudentInfo = [[NSMutableArray alloc] init];
    self.arrSearchInfo = [[NSMutableArray alloc] init];

    StudentInfo *student_1 = [[StudentInfo alloc] init];
    student_1.name = @"Sia S";
    student_1.style = @"S";
    student_1.trend = @"S";
    student_1.age = @"60";
    student_1.locale = @"Node";
    student_1.street = @"BR";
    student_1.city = @"JP";
    student_1.country = @"US";
    student_1.isOpen = YES;
    student_1.isShowMore = NO;
    [self.arrStudentInfo addObject:student_1];

    StudentInfo *student_2 = [[StudentInfo alloc] init];
    student_2.name = @"Nitin";
    student_2.style = @"N";
    student_2.trend = @"N";
    student_2.age = @"40";
    student_2.locale = @"Node";
    student_2.street = @"BR";
    student_2.city = @"SP";
    student_2.country = @"US";
    student_2.isOpen = YES;
    student_2.isShowMore = NO;
    [self.arrStudentInfo addObject:student_2];
}
我已经创建了一个返回当前活动的方法,它意味着搜索记录或数组的原始记录

- (NSMutableArray *)getCurrentArray {

    if(self.isSearch)
        return self.arrSearchInfo;
    else
        return self.arrStudentInfo;
}
根据场景加载数据

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    StudentInfo *studentInfo = [self getCurrentArray][indexPath.section];

    if(indexPath.row == SHOW_MORE_INDEX && studentInfo.isShowMore == NO) {

        static NSString *strCellIdentifier = @"ShowMoreCell";
        ShowMoreCell *cell = [tableView dequeueReusableCellWithIdentifier:strCellIdentifier];
        cell.btnShowMore.tag = indexPath.section;
        [cell.btnShowMore addTarget:self action:@selector(clickONShowMore:) forControlEvents:UIControlEventTouchUpInside];

        return cell;
    }

    else {

        static NSString *strCellIdentifier = @"StudentListCell";

        StudentListCell *cell = [tableView dequeueReusableCellWithIdentifier:strCellIdentifier];
        [cell setupCell:studentInfo indexPath:indexPath];

        return cell;
    }
}
用于搜索学生姓名

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {

    [searchBar resignFirstResponder];
    self.isSearch = YES;

    NSPredicate *predicateStudent = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"self.name CONTAINS[cd] '%@'",searchBar.text]];
    NSArray *arrGetSearch = [self.arrStudentInfo filteredArrayUsingPredicate:predicateStudent];

    if(self.arrSearchInfo.count)
        [self.arrSearchInfo removeAllObjects];

    [self.arrSearchInfo addObjectsFromArray:arrGetSearch];
    [self.tblView reloadData];
}
如果用户单击
UISearchbar
上的“X”按钮,则再次加载原始记录

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {

    if([searchText isEqualToString:@""] || searchText==nil) {

        [searchBar resignFirstResponder];
        self.isSearch = NO;
        [self.tblView reloadData];
    }
}

希望这对您有用。

一些问题可以更好地了解您的需求。1.如果学生部分中没有与搜索匹配的行,会发生什么情况?2.按钮“显示剩余”是否只影响每个部分,还是所有部分都打开按钮?@Sergii Martynenko Jr-每个部分都有“显示剩余”按钮。如果某个部分中没有匹配项,则该部分被隐藏或删除。如果您向我们提供反馈,那会很好,有任何答案对您有帮助吗?@Sergii Martynenko J,Ramkrishna Sharma,Hasya-感谢很多人对您的及时帮助。实际上,从某种意义上说,这不是最好的方法。例如,您将属性“isShowMore”放置在模型类Student中,这是一种糟糕的做法。“全部显示”选项与模型无关,哪个学生班是。感谢您的评论,实际上我在模型中使用了isShowMore标志来标识每个记录是否允许显示更多。请让我知道我是否需要放置它。