30
30
#import < objc/runtime.h>
31
31
32
32
#pragma mark -
33
- #pragma mark - FZAccordionTableViewSection
33
+ #pragma mark - FZAccordionTableViewSectionInfo
34
34
#pragma mark -
35
35
36
- @interface FZAccordionTableViewSection : NSObject
36
+ @interface FZAccordionTableViewSectionInfo : NSObject
37
37
@property (nonatomic , getter =isOpen) BOOL open;
38
38
@property (nonatomic ) NSInteger numberOfRows;
39
39
@end
40
40
41
- @implementation FZAccordionTableViewSection
41
+ @implementation FZAccordionTableViewSectionInfo
42
42
- (instancetype )initWithNumberOfRows : (NSInteger )numberOfRows {
43
43
if (self = [super init ]) {
44
44
_numberOfRows = numberOfRows;
@@ -55,7 +55,6 @@ @protocol FZAccordionTableViewHeaderViewDelegate;
55
55
56
56
@interface FZAccordionTableViewHeaderView ()
57
57
58
- // @property (nonatomic) NSInteger section;
59
58
@property (nonatomic , weak ) id <FZAccordionTableViewHeaderViewDelegate> delegate;
60
59
61
60
@end
@@ -99,9 +98,8 @@ @interface FZAccordionTableView() <UITableViewDataSource, UITableViewDelegate, F
99
98
@property id <UITableViewDelegate, FZAccordionTableViewDelegate> subclassDelegate;
100
99
@property id <UITableViewDataSource> subclassDataSource;
101
100
102
- // @property (strong, nonatomic) NSMutableSet *openedSections;
103
- // @property (strong, nonatomic) NSMutableDictionary *numOfRowsForSection;
104
- @property (strong , nonatomic ) NSMutableArray <FZAccordionTableViewSection *> *sections; // <FZAccordionTableViewSection *>
101
+ @property (strong , nonatomic ) NSMutableSet *mutableInitialOpenSections;
102
+ @property (strong , nonatomic ) NSMutableArray <FZAccordionTableViewSectionInfo *> *sectionInfos;
105
103
106
104
@end
107
105
@@ -138,9 +136,7 @@ - (id)init {
138
136
}
139
137
140
138
- (void )initializeVars {
141
- // _openedSections = [[NSMutableSet alloc] init];
142
- // _numOfRowsForSection = [NSMutab
143
- _sections = [NSMutableArray new ];
139
+ _sectionInfos = [NSMutableArray new ];
144
140
_allowMultipleSectionsOpen = NO ;
145
141
_enableAnimationFix = NO ;
146
142
_keepOneSectionOpen = NO ;
@@ -149,24 +145,24 @@ - (void)initializeVars {
149
145
#pragma mark - Helper methods -
150
146
151
147
- (BOOL )isSectionOpen : (NSInteger )section {
152
- return [self .sections [section] isOpen ];
148
+ return [self .sectionInfos [section] isOpen ];
153
149
}
154
150
155
151
- (BOOL )isAlwaysOpenedSection : (NSInteger )section {
156
152
return [self .sectionsAlwaysOpen containsObject: @(section)];
157
153
}
158
154
159
155
- (void )addOpenedSection : (NSInteger )section { // KRIS TODO: Rename this to markSectionOpen
160
- [self .sections [section] setOpen: YES ];
156
+ [self .sectionInfos [section] setOpen: YES ];
161
157
}
162
158
163
159
- (void )removeOpenedSection : (NSInteger )section {
164
- [self .sections [section] setOpen: NO ];
160
+ [self .sectionInfos [section] setOpen: NO ];
165
161
}
166
162
167
163
- (NSArray *)getIndexPathsForSection : (NSInteger )section {
168
164
169
- NSInteger numOfRows = [self .sections [section] numberOfRows ];
165
+ NSInteger numOfRows = [self .sectionInfos [section] numberOfRows ];
170
166
NSMutableArray *indexPaths = [NSMutableArray array ];
171
167
for (int row = 0 ; row < numOfRows; row++) {
172
168
[indexPaths addObject: [NSIndexPath indexPathForRow: row inSection: section]];
@@ -202,6 +198,7 @@ - (NSInteger)sectionForHeaderView:(UITableViewHeaderFooterView *)headerView {
202
198
}
203
199
else {
204
200
maxSection = middleSection-1 ;
201
+ section = maxSection; // Occurs when headerView sticks to the top
205
202
}
206
203
}
207
204
@@ -222,13 +219,25 @@ - (void)setDataSource:(id<UITableViewDataSource>)dataSource {
222
219
223
220
- (void )deleteSections : (NSIndexSet *)sections withRowAnimation : (UITableViewRowAnimation)animation {
224
221
225
- [sections enumerateIndexesUsingBlock: ^(NSUInteger section, BOOL * _Nonnull stop) {
226
- [self .sections removeObjectAtIndex: section];
227
- // KRIS TODO: If the removed section is one that needs ot be oepned, we need to open the next section.
228
- // OR Refactor sections open to just be a delegate call "canOpen Section
229
- // [self.openedSections removeObject:@(section)];
222
+ // Remove section info in reverse order to prevent array from
223
+ // removing the wrong section due to the stacking effect of arrays
224
+ [sections enumerateIndexesWithOptions: NSEnumerationReverse usingBlock: ^(NSUInteger section, BOOL * _Nonnull stop) {
225
+ [self .sectionInfos removeObjectAtIndex: section];
230
226
}];
227
+
231
228
[super deleteSections: sections withRowAnimation: animation];
229
+
230
+ // Re-open any sections that were closed by deletion, but
231
+ // must be always open.
232
+ if (self.sectionsAlwaysOpen .count > 0 ) {
233
+ [sections enumerateIndexesWithOptions: NSEnumerationReverse usingBlock: ^(NSUInteger section, BOOL * _Nonnull stop) {
234
+ if ([self .sectionsAlwaysOpen containsObject: @(section)] && ![self isSectionOpen: section]) {
235
+ FZAccordionTableViewHeaderView *sectionHeaderView = (FZAccordionTableViewHeaderView *)[self headerViewForSection: section];
236
+ NSArray *indexPathsToModify = [self getIndexPathsForSection: section];
237
+ [self openSection: section withHeaderView: sectionHeaderView andIndexPaths: indexPathsToModify];
238
+ }
239
+ }];
240
+ }
232
241
}
233
242
234
243
#pragma mark - Forwarding handling -
@@ -250,24 +259,9 @@ - (BOOL)respondsToSelector:(SEL)aSelector {
250
259
251
260
#pragma mark - Override Setters -
252
261
253
- - (void )setSectionsAlwaysOpen : (NSSet *)alwaysOpenedSections {
254
- _sectionsAlwaysOpen = alwaysOpenedSections;
255
-
256
- // if (_sectionsAlwaysOpen != nil) {
257
- // for (NSNumber *alwaysOpenedSection in _sectionsAlwaysOpen) {
258
- // [self addOpenedSection:alwaysOpenedSection.integerValue];
259
- // }
260
- // }
261
- }
262
-
263
262
- (void )setInitialOpenSections : (NSSet *)initialOpenedSections {
264
263
_initialOpenSections = initialOpenedSections;
265
-
266
- // if (_initialOpenSections != nil) {
267
- // for (NSNumber *section in _initialOpenSections) {
268
- // [self addOpenedSection:section.integerValue];
269
- // }
270
- // }
264
+ _mutableInitialOpenSections = [initialOpenedSections mutableCopy ];
271
265
}
272
266
273
267
#pragma mark - FZAccordionTableViewHeaderViewDelegate -
@@ -287,16 +281,16 @@ - (void)tappedHeaderView:(FZAccordionTableViewHeaderView *)sectionHeaderView {
287
281
NSInteger countOfOpenSections = 0 ;
288
282
289
283
for (NSInteger i = 0 ; i < self.numberOfSections ; i++) {
290
- if ([self .sections [i] isOpen ]) {
284
+ if ([self .sectionInfos [i] isOpen ]) {
291
285
countOfOpenSections++;
292
286
}
293
287
}
294
288
295
- // if (self.sectionsAlwaysOpen.count > 0) { // Subtract 'sectionsAlwaysOpen' from 'openedSections'
296
- // NSMutableSet *openedSectionsCopy = [self.openedSections mutableCopy];
297
- // [openedSectionsCopy minusSet:self.sectionsAlwaysOpen];
298
- // countOfOpenSections = openedSectionsCopy .count;
299
- // }
289
+ if (self.sectionsAlwaysOpen .count > 0 ) {
290
+ // 'sectionsAlwaysOpen' does not have an influence
291
+ // on 'keepOneSectionOpen'
292
+ countOfOpenSections -= self. sectionsAlwaysOpen .count ;
293
+ }
300
294
301
295
if (countOfOpenSections == 1 && [self isSectionOpen: section]) {
302
296
return ;
@@ -336,20 +330,18 @@ - (void)openSection:(NSInteger)section withHeaderView:(FZAccordionTableViewHeade
336
330
// If any section is open beneath the one we are trying to open,
337
331
// animate from the bottom
338
332
for (NSInteger i = section-1 ; i >= 0 ; i--) {
339
- if ([self .sections [i] isOpen ]) {
333
+ if ([self .sectionInfos [i] isOpen ]) {
340
334
insertAnimation = UITableViewRowAnimationBottom;
341
335
}
342
336
}
343
337
}
344
338
345
- // KRIS TODO: Fix
346
- // if (self.enableAnimationFix) {
347
- // if (self.openedSections.count > 0 &&
348
- // (section == self.sections.count-1 || section == self.sections.count-2) &&
349
- // !self.allowsMultipleSelection) {
350
- // insertAnimation = UITableViewRowAnimationFade;
351
- // }
352
- // }
339
+ if (self.enableAnimationFix ) {
340
+ if (!self.allowsMultipleSelection &&
341
+ (section == self.numberOfSections -1 || section == self.numberOfSections -2 )) {
342
+ insertAnimation = UITableViewRowAnimationFade;
343
+ }
344
+ }
353
345
354
346
[self addOpenedSection: section];
355
347
[self beginUpdates ];
@@ -382,7 +374,7 @@ - (void)autoCollapseAllSectionsExceptSection:(NSInteger)section {
382
374
// Get all of the sections that we need to close
383
375
NSMutableSet *sectionsToClose = [[NSMutableSet alloc ] init ];
384
376
for (NSInteger i = 0 ; i < self.numberOfSections ; i++) {
385
- FZAccordionTableViewSection *sectionInfo = self.sections [i];
377
+ FZAccordionTableViewSectionInfo *sectionInfo = self.sectionInfos [i];
386
378
if (section != i && sectionInfo.isOpen && ![self isAlwaysOpenedSection: i]) {
387
379
[sectionsToClose addObject: @(i)];
388
380
}
@@ -401,9 +393,9 @@ - (void)autoCollapseAllSectionsExceptSection:(NSInteger)section {
401
393
closeAnimation = UITableViewRowAnimationBottom;
402
394
}
403
395
if (self.enableAnimationFix ) {
404
- if ((sectionToClose. integerValue == self.sections . count - 1 ||
405
- sectionToClose.integerValue == self.sections .count - 2 ) &&
406
- ! self.allowsMultipleSelection ) {
396
+ if (! self.allowsMultipleSelection &&
397
+ ( sectionToClose.integerValue == self.sectionInfos .count - 1 ||
398
+ sectionToClose. integerValue == self.sectionInfos . count - 2 ) ) {
407
399
closeAnimation = UITableViewRowAnimationFade;
408
400
}
409
401
}
@@ -434,29 +426,23 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
434
426
numOfSections = [self .subclassDataSource numberOfSectionsInTableView: tableView];
435
427
}
436
428
437
- // Initialize an empty array filled with @(0)
438
- // id sections[numOfSections];
439
- // memset(sections, (int)[NSNumber numberWithInt:0], numOfSections);
440
- // self.numberOfRowsInSection = [NSMutableArray arrayWithObjects:sections count:numOfSections];
441
- // self.numberOfRowsInSection = [NSMutableArray arrayWithCapacity:numOfSections];
442
- // NSMutableArray *newNumberOfRowsInSection = [NSMutableArray arrayWithCapacity:numOfSections];
443
-
444
- for (NSInteger i = self.sections .count ; i < numOfSections; i++) {
445
- FZAccordionTableViewSection *section = [[FZAccordionTableViewSection alloc ] initWithNumberOfRows: 0 ];
446
- section.open = NO ;
447
- [self .sections addObject: section];
448
- // KRIS TO DO: Handle sections always open and initial open sections.
429
+ // Create 'FZAccordionTableViewSectionInfo' objects to represent each section
430
+ for (NSInteger i = self.sectionInfos .count ; i < numOfSections; i++) {
431
+ FZAccordionTableViewSectionInfo *section = [[FZAccordionTableViewSectionInfo alloc ] initWithNumberOfRows: 0 ];
432
+
433
+ // Account for any initial open sections
434
+ if (self.mutableInitialOpenSections .count > 0 && [self .mutableInitialOpenSections containsObject: @(i)]) {
435
+ section.open = YES ;
436
+ [self .mutableInitialOpenSections removeObject: @(i)];
437
+ }
438
+ // Account for sections that are always open
439
+ else {
440
+ section.open = [self .sectionsAlwaysOpen containsObject: @(i)];
441
+ }
442
+
443
+ [self .sectionInfos addObject: section];
449
444
}
450
445
451
-
452
- // First time
453
- // it's less
454
- // it's more
455
-
456
-
457
- // we must maintain the correct size, yet also copy in the left-over elements.
458
-
459
-
460
446
return numOfSections;
461
447
}
462
448
@@ -467,7 +453,7 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger
467
453
if ([self .subclassDataSource respondsToSelector: @selector (tableView:numberOfRowsInSection: )]) {
468
454
numOfRows = [self .subclassDataSource tableView: tableView numberOfRowsInSection: section];;
469
455
}
470
- [self .sections [section] setNumberOfRows: numOfRows];
456
+ [self .sectionInfos [section] setNumberOfRows: numOfRows];
471
457
472
458
return ([self isSectionOpen: section]) ? numOfRows : 0 ;
473
459
}
0 commit comments