Я нашел другой относительно простой способ решения этой проблемы. При использовании этого метода нам не потребуется изменять нашу ячейку, которая почти всегда связана с индексом массива данных, что может вызвать беспорядок в нашем контроллере представления.
Сначала мы добавим следующие свойства в наш класс контроллера:
@property (strong, nonatomic) NSMutableArray* collapsedSections;
@property (strong, nonatomic) NSMutableArray* sectionViews;
collapsedSections
сохранит свернутые номера разделов.
sectionViews
будет хранить наш пользовательский вид сечения.
Синтезируйте это:
@synthesize collapsedSections;
@synthesize sectionViews;
Инициализируйте это:
- (void) viewDidLoad
{
[super viewDidLoad];
self.collapsedSections = [NSMutableArray array];
self.sectionViews = [NSMutableArray array];
}
После этого мы должны подключить наш UITableView, чтобы к нему можно было получить доступ из нашего класса контроллера представления:
@property (strong, nonatomic) IBOutlet UITableView *tblMain;
Подключите его из XIB для просмотра контроллера, используя ctrl + drag
, как обычно.
Затем мы создаем представление в качестве пользовательского заголовка раздела для нашего табличного представления путем реализации этого делегата UITableView:
- (UIView*) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
// Create View
CGRect frame = CGRectZero;
frame.origin = CGPointZero;
frame.size.height = 30.f;
frame.size.width = tableView.bounds.size.width;
UIView* view = [[UIView alloc] initWithFrame:frame];
[view setBackgroundColor:[UIColor blueColor]];
// Add label for title
NSArray* titles = @[@"Title 1", @"Title 2", @"Title 3"];
NSString* selectedTitle = [titles objectAtIndex:section];
CGRect labelFrame = frame;
labelFrame.size.height = 30.f;
labelFrame.size.width -= 20.f;
labelFrame.origin.x += 10.f;
UILabel* titleLabel = [[UILabel alloc] initWithFrame:labelFrame];
[titleLabel setText:selectedTitle];
[titleLabel setTextColor:[UIColor whiteColor]];
[view addSubview:titleLabel];
// Add touch gesture
[self attachTapGestureToView:view];
// Save created view to our class property array
[self saveSectionView:view inSection:section];
return view;
}
Далее мы реализуем метод для сохранения нашего ранее созданного пользовательского заголовка раздела в свойстве класса:
- (void) saveSectionView:(UIView*) view inSection:(NSInteger) section
{
NSInteger sectionCount = [self numberOfSectionsInTableView:[self tblMain]];
if(section < sectionCount)
{
if([[self sectionViews] indexOfObject:view] == NSNotFound)
{
[[self sectionViews] addObject:view];
}
}
}
Добавьте UIGestureRecognizerDelegate
к нашему файлу контроллера представления .h:
@interface MyViewController : UIViewController<UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate>
Затем мы создаем метод attachTapGestureToView:
- (void) attachTapGestureToView:(UIView*) view
{
UITapGestureRecognizer* tapAction = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap:)];
[tapAction setDelegate:self];
[view addGestureRecognizer:tapAction];
}
Вышеуказанный метод добавит распознаватель жестов касания ко всему виду разреза, который мы создали ранее. Далее мы должны реализовать onTap:
селектор
- (void) onTap:(UITapGestureRecognizer*) gestureRecognizer
{
// Take view who attach current recognizer
UIView* sectionView = [gestureRecognizer view];
// [self sectionViews] is Array containing our custom section views
NSInteger section = [self sectionNumberOfView:sectionView];
// [self tblMain] is our connected IBOutlet table view
NSInteger sectionCount = [self numberOfSectionsInTableView:[self tblMain]];
// If section more than section count minus one set at last
section = section > (sectionCount - 1) ? 2 : section;
[self toggleCollapseSection:section];
}
Вышеуказанный метод будет вызван, когда пользователь коснется любого из нашего раздела табличного представления. Этот метод ищет правильный номер раздела на основе нашего sectionViews
массива, который мы создали ранее.
Кроме того, мы реализуем метод для получения раздела заголовка, к которому относится.
- (NSInteger) sectionNumberOfView:(UIView*) view
{
UILabel* label = [[view subviews] objectAtIndex:0];
NSInteger sectionNum = 0;
for(UIView* sectionView in [self sectionViews])
{
UILabel* sectionLabel = [[sectionView subviews] objectAtIndex:0];
//NSLog(@"Section: %d -> %@ vs %@", sectionNum, [label text], [sectionLabel text]);
if([[label text] isEqualToString:[sectionLabel text]])
{
return sectionNum;
}
sectionNum++;
}
return NSNotFound;
}
Далее мы должны реализовать метод toggleCollapseSection:
- (void) toggleCollapseSection:(NSInteger) section
{
if([self isCollapsedSection:section])
{
[self removeCollapsedSection:section];
}
else
{
[self addCollapsedSection:section];
}
[[self tblMain] reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
}
Этот метод вставляет / удаляет номер раздела в нашем массиве collapsedSections
, который мы создали ранее. Когда номер раздела вставляется в этот массив, это означает, что раздел должен быть свернут и расширен, если в противном случае.
Далее мы реализуем removeCollapsedSection:
, addCollapsedSection:section
и isCollapsedSection:section
- (BOOL)isCollapsedSection:(NSInteger) section
{
for(NSNumber* existing in [self collapsedSections])
{
NSInteger current = [existing integerValue];
if(current == section)
{
return YES;
}
}
return NO;
}
- (void)removeCollapsedSection:(NSInteger) section
{
[[self collapsedSections] removeObjectIdenticalTo:[NSNumber numberWithInteger:section]];
}
- (void)addCollapsedSection:(NSInteger) section
{
[[self collapsedSections] addObject:[NSNumber numberWithInteger:section]];
}
Эти три метода просто помогают нам получить доступ к массиву collapsedSections
.
Наконец, реализуйте этот делегат табличного представления, чтобы наши пользовательские представления секций выглядели хорошо.
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 30.f; // Same as each custom section view height
}
Надеюсь, это поможет.