From 599f917e6d4ff73777e98d305992dad7058502d6 Mon Sep 17 00:00:00 2001 From: BandarHelal <31299470+BandarHL@users.noreply.github.com> Date: Wed, 20 Jul 2022 22:30:44 +0300 Subject: [PATCH 1/2] Allow hiding multiple cells --- .DS_Store | Bin 0 -> 6148 bytes Dynamic Specifiers/XXXRootListController.h | 8 +- Dynamic Specifiers/XXXRootListController.m | 285 +++++++++++---------- 3 files changed, 153 insertions(+), 140 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9434d91ef8dfd7b3e1890699a164e4f183d57e6c GIT binary patch literal 6148 zcmeHKQA+|r5S~@b6A2^=d|c>N$W(;rOOsD!x^HeU#hlP*cldI*J{;{hVL1_>Sv zmZI759~q#t+k`GWK>|K}KEDu8GJ+e_5QdNjlXMWoD!};HU=T;?s9t{)xqM-5z33F3 zvUBO(sfjo8N8_~P56`K0qEsBrZ9h1T!bz{Pb*Pe&A0^>XCq(@aLoUvuq^~9&HBS1e z&h^ZIQ*uhZN_9GIwCgq5Y_(=JIo)rd-Dgs#QRpuRe= zq2EUuFA$QTO>YT8Y0M4{_-JGdoVTbDLRwN|2Dp^{Ks nX7D2g4PA;cmP&CIRSWth8HldM%piJD_(wp~zzs9-rwqIU;-*st literal 0 HcmV?d00001 diff --git a/Dynamic Specifiers/XXXRootListController.h b/Dynamic Specifiers/XXXRootListController.h index bd3c7dc..b1b1f9d 100644 --- a/Dynamic Specifiers/XXXRootListController.h +++ b/Dynamic Specifiers/XXXRootListController.h @@ -12,7 +12,7 @@ typedef NS_ENUM(NSInteger, XXDynamicSpecifierOperatorType) { @interface XXXRootListController : PSListController @property (nonatomic, assign) BOOL hasDynamicSpecifiers; @property (nonatomic, retain) NSMutableDictionary *dynamicSpecifiers; --(void)collectDynamicSpecifiersFromArray:(NSArray *)array; --(BOOL)shouldHideSpecifier:(PSSpecifier *)specifier; --(XXDynamicSpecifierOperatorType)operatorTypeForString:(NSString *)string; -@end \ No newline at end of file +- (void)collectDynamicSpecifiersFromArray:(NSArray *)array; +- (BOOL)shouldHideSpecifier:(PSSpecifier *)specifier; +- (XXDynamicSpecifierOperatorType)operatorTypeForString:(NSString *)string; +@end diff --git a/Dynamic Specifiers/XXXRootListController.m b/Dynamic Specifiers/XXXRootListController.m index 8b02822..d46c52e 100644 --- a/Dynamic Specifiers/XXXRootListController.m +++ b/Dynamic Specifiers/XXXRootListController.m @@ -4,146 +4,159 @@ @implementation XXXRootListController #pragma mark - Collect Dynamic Specifiers - -(NSArray *)specifiers { - if (!_specifiers) { - _specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self]; - - [self collectDynamicSpecifiersFromArray:_specifiers]; - } - - return _specifiers; - } - - -(void)reloadSpecifiers { - [super reloadSpecifiers]; - - [self collectDynamicSpecifiersFromArray:self.specifiers]; - } - - -(void)collectDynamicSpecifiersFromArray:(NSArray *)array { - //Create new dictionary or remove all previous specifiers - if(!self.dynamicSpecifiers) { - self.dynamicSpecifiers = [NSMutableDictionary new]; - - } else { - [self.dynamicSpecifiers removeAllObjects]; - } - - //Add any specifiers with rule to dynamic specifiers dictionary - for(PSSpecifier *specifier in array) { - NSString *dynamicSpecifierRule = [specifier propertyForKey:@"dynamicRule"]; - - if(dynamicSpecifierRule.length > 0) { - //Get rule components - NSArray *ruleComponents = [dynamicSpecifierRule componentsSeparatedByString:@", "]; - - //Add specifier to dictionary with opposing specifier ID as key - if(ruleComponents.count == 3) { - NSString *opposingSpecifierID = [ruleComponents objectAtIndex:0]; - [self.dynamicSpecifiers setObject:specifier forKey:opposingSpecifierID]; - - //Throw error if rule has incorrect components - } else { - [NSException raise:NSInternalInconsistencyException format:@"dynamicRule key requires three components (Specifier ID, Comparator, Value To Compare To). You have %ld of 3 (%@) for specifier '%@'.", ruleComponents.count, dynamicSpecifierRule, [specifier propertyForKey:PSTitleKey]]; - } - } - } - - //Check if we need to update specifier height at all - self.hasDynamicSpecifiers = (self.dynamicSpecifiers.count > 0); - } +- (NSArray *)specifiers { + if (!_specifiers) { + _specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self]; + + [self collectDynamicSpecifiersFromArray:_specifiers]; + } + + return _specifiers; +} + +- (void)reloadSpecifiers { + [super reloadSpecifiers]; + + [self collectDynamicSpecifiersFromArray:self.specifiers]; +} + +- (void)collectDynamicSpecifiersFromArray:(NSArray *)array { + //Create new dictionary or remove all previous specifiers + if (!self.dynamicSpecifiers) { + self.dynamicSpecifiers = [NSMutableDictionary new]; + + } else { + [self.dynamicSpecifiers removeAllObjects]; + } + + //Add any specifiers with rule to dynamic specifiers dictionary + for (PSSpecifier *specifier in array) { + NSString *dynamicSpecifierRule = [specifier propertyForKey:@"dynamicRule"]; + + if (dynamicSpecifierRule.length > 0) { + //Get rule components + NSArray *ruleComponents = [dynamicSpecifierRule componentsSeparatedByString:@", "]; + + //Add specifier to dictionary with opposing specifier ID as key + if (ruleComponents.count == 3) { + NSString *opposingSpecifierID = [ruleComponents objectAtIndex:0]; + + if ([self.dynamicSpecifiers objectForKey:opposingSpecifierID]) { + NSMutableArray *specifiers = [[self.dynamicSpecifiers objectForKey:opposingSpecifierID] mutableCopy]; + [specifiers addObject:specifier]; + + + [self.dynamicSpecifiers removeObjectForKey:opposingSpecifierID]; + [self.dynamicSpecifiers setObject:specifiers forKey:opposingSpecifierID]; + } else { + [self.dynamicSpecifiers setObject:[NSMutableArray arrayWithArray:@[specifier]] forKey:opposingSpecifierID]; + } + + //Throw error if rule has incorrect components + } else { + [NSException raise:NSInternalInconsistencyException format:@"dynamicRule key requires three components (Specifier ID, Comparator, Value To Compare To). You have %ld of 3 (%@) for specifier '%@'.", ruleComponents.count, dynamicSpecifierRule, [specifier propertyForKey:PSTitleKey]]; + } + } + } + + //Check if we need to update specifier height at all + self.hasDynamicSpecifiers = (self.dynamicSpecifiers.count > 0); +} #pragma mark - Observing Opposing Specifier Value Changes - -(void)setPreferenceValue:(id)value specifier:(PSSpecifier *)specifier { - [super setPreferenceValue:value specifier:specifier]; - - if(self.hasDynamicSpecifiers) { - //Check if dynamic specifier exists for opposing specifier ID - NSString *specifierID = [specifier propertyForKey:PSIDKey]; - PSSpecifier *dynamicSpecifier = [self.dynamicSpecifiers objectForKey:specifierID]; - - //Update cells - if(dynamicSpecifier) { - [self.table beginUpdates]; - [self.table endUpdates]; - } - } - } +- (void)setPreferenceValue:(id)value specifier:(PSSpecifier *)specifier { + [super setPreferenceValue:value specifier:specifier]; + + if (self.hasDynamicSpecifiers) { + //Check if dynamic specifier exists for opposing specifier ID + NSString *specifierID = [specifier propertyForKey:PSIDKey]; + PSSpecifier *dynamicSpecifier = [self.dynamicSpecifiers objectForKey:specifierID]; + + //Update cells + if (dynamicSpecifier) { + [self.table beginUpdates]; + [self.table endUpdates]; + } + } +} #pragma mark - Override Height - -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - if(self.hasDynamicSpecifiers) { - PSSpecifier *dynamicSpecifier = [self specifierAtIndexPath:indexPath]; - - //Check if specifier exists in our dictionary values - if([self.dynamicSpecifiers.allValues containsObject:dynamicSpecifier]) { - BOOL shouldHide = [self shouldHideSpecifier:dynamicSpecifier]; - - //Clips bounds if we're hiding the cell - UITableViewCell *specifierCell = [dynamicSpecifier propertyForKey:PSTableCellKey]; - specifierCell.clipsToBounds = shouldHide; - - if(shouldHide) { - return 0; - } - } - } - - return UITableViewAutomaticDimension; - } - - -(BOOL)shouldHideSpecifier:(PSSpecifier *)specifier { - if(specifier) { - //Get dynamic rule components - NSString *dynamicSpecifierRule = [specifier propertyForKey:@"dynamicRule"]; - NSArray *ruleComponents = [dynamicSpecifierRule componentsSeparatedByString:@", "]; - - //Get values to compare to specifier's value - PSSpecifier *opposingSpecifier = [self specifierForID:[ruleComponents objectAtIndex:0]]; - id opposingValue = [self readPreferenceValue:opposingSpecifier]; - id requiredValue = [ruleComponents objectAtIndex:2]; - - //Numbers can use any operator - if([opposingValue isKindOfClass:NSNumber.class]) { - XXDynamicSpecifierOperatorType operatorType = [self operatorTypeForString:[ruleComponents objectAtIndex:1]]; - - switch(operatorType) { - case XXEqualToOperatorType: - return ([opposingValue intValue] == [requiredValue intValue]); - break; - - case XXNotEqualToOperatorType: - return ([opposingValue intValue] != [requiredValue intValue]); - break; - - case XXGreaterThanOperatorType: - return ([opposingValue intValue] > [requiredValue intValue]); - break; - - case XXLessThanOperatorType: - return ([opposingValue intValue] < [requiredValue intValue]); - break; - } - } - - //Strings can only check if equal - if([opposingValue isKindOfClass:NSString.class]) { - return [opposingValue isEqualToString:requiredValue]; - } - - //Arrays can check if value exists - if([opposingValue isKindOfClass:NSArray.class]) { - return [opposingValue containsObject:requiredValue]; - } - } - - return NO; - } - - -(XXDynamicSpecifierOperatorType)operatorTypeForString:(NSString *)string { - NSDictionary *operatorValues = @{ @"==" : @(XXEqualToOperatorType), @"!=" : @(XXNotEqualToOperatorType), @">" : @(XXGreaterThanOperatorType), @"<" : @(XXLessThanOperatorType) }; - return [operatorValues[string] intValue]; - } +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + if (self.hasDynamicSpecifiers) { + PSSpecifier *dynamicSpecifier = [self specifierAtIndexPath:indexPath]; + BOOL __block shouldHide = false; + + //Check if specifier exists in our dictionary values + [self.dynamicSpecifiers enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + NSMutableArray *specifiers = obj; + if ([specifiers containsObject:dynamicSpecifier]) { + shouldHide = [self shouldHideSpecifier:dynamicSpecifier]; + + UITableViewCell *specifierCell = [dynamicSpecifier propertyForKey:PSTableCellKey]; + specifierCell.clipsToBounds = shouldHide; + } + }]; + + if (shouldHide) { + return 0; + } + } + + return UITableViewAutomaticDimension; +} + +- (BOOL)shouldHideSpecifier:(PSSpecifier *)specifier { + if (specifier) { + //Get dynamic rule components + NSString *dynamicSpecifierRule = [specifier propertyForKey:@"dynamicRule"]; + NSArray *ruleComponents = [dynamicSpecifierRule componentsSeparatedByString:@", "]; + + //Get values to compare to specifier's value + PSSpecifier *opposingSpecifier = [self specifierForID:[ruleComponents objectAtIndex:0]]; + id opposingValue = [self readPreferenceValue:opposingSpecifier]; + id requiredValue = [ruleComponents objectAtIndex:2]; + + //Numbers can use any operator + if ([opposingValue isKindOfClass:NSNumber.class]) { + XXDynamicSpecifierOperatorType operatorType = [self operatorTypeForString:[ruleComponents objectAtIndex:1]]; + + switch(operatorType) { + case XXEqualToOperatorType: + return ([opposingValue intValue] == [requiredValue intValue]); + break; + + case XXNotEqualToOperatorType: + return ([opposingValue intValue] != [requiredValue intValue]); + break; + + case XXGreaterThanOperatorType: + return ([opposingValue intValue] > [requiredValue intValue]); + break; + + case XXLessThanOperatorType: + return ([opposingValue intValue] < [requiredValue intValue]); + break; + } + } + + //Strings can only check if equal + if ([opposingValue isKindOfClass:NSString.class]) { + return [opposingValue isEqualToString:requiredValue]; + } + + //Arrays can check if value exists + if ([opposingValue isKindOfClass:NSArray.class]) { + return [opposingValue containsObject:requiredValue]; + } + } + + return NO; +} + +- (XXDynamicSpecifierOperatorType)operatorTypeForString:(NSString *)string { + NSDictionary *operatorValues = @{ @"==" : @(XXEqualToOperatorType), @"!=" : @(XXNotEqualToOperatorType), @">" : @(XXGreaterThanOperatorType), @"<" : @(XXLessThanOperatorType) }; + return [operatorValues[string] intValue]; +} @end From 20c5bfb31151233ae75f8ad590a258a2c7194b86 Mon Sep 17 00:00:00 2001 From: BandarHelal <31299470+BandarHL@users.noreply.github.com> Date: Wed, 20 Jul 2022 22:34:39 +0300 Subject: [PATCH 2/2] update codes in README.md --- Dynamic Specifiers/README.md | 92 ++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/Dynamic Specifiers/README.md b/Dynamic Specifiers/README.md index a103fd0..0bab9f4 100644 --- a/Dynamic Specifiers/README.md +++ b/Dynamic Specifiers/README.md @@ -80,31 +80,40 @@ 5. Add the method `collectDynamicSpecifiersFromArray:` to your RootListController. This method adds the dynamic specifier to the `dynamicSpecifiers` dictionary with the opposing specifier's `id` as the key. Call this method from the `-specifiers` method and `-reloadSpecifiers`: ```objc --(void)collectDynamicSpecifiersFromArray:(NSArray *)array { - if(!self.dynamicSpecifiers) { - self.dynamicSpecifiers = [NSMutableDictionary new]; - - } else { - [self.dynamicSpecifiers removeAllObjects]; - } - - for(PSSpecifier *specifier in array) { - NSString *dynamicSpecifierRule = [specifier propertyForKey:@"dynamicRule"]; - - if(dynamicSpecifierRule.length > 0) { - NSArray *ruleComponents = [dynamicSpecifierRule componentsSeparatedByString:@", "]; - - if(ruleComponents.count == 3) { - NSString *opposingSpecifierID = [ruleComponents objectAtIndex:0]; - [self.dynamicSpecifiers setObject:specifier forKey:opposingSpecifierID]; - - } else { - [NSException raise:NSInternalInconsistencyException format:@"dynamicRule key requires three components (Specifier ID, Comparator, Value To Compare To). You have %ld of 3 (%@) for specifier '%@'.", ruleComponents.count, dynamicSpecifierRule, [specifier propertyForKey:PSTitleKey]]; - } +- (void)collectDynamicSpecifiersFromArray:(NSArray *)array { + if (!self.dynamicSpecifiers) { + self.dynamicSpecifiers = [NSMutableDictionary new]; + + } else { + [self.dynamicSpecifiers removeAllObjects]; } - } - - self.hasDynamicSpecifiers = (self.dynamicSpecifiers.count > 0); + + for (PSSpecifier *specifier in array) { + NSString *dynamicSpecifierRule = [specifier propertyForKey:@"dynamicRule"]; + + if (dynamicSpecifierRule.length > 0) { + NSArray *ruleComponents = [dynamicSpecifierRule componentsSeparatedByString:@", "]; + + if (ruleComponents.count == 3) { + NSString *opposingSpecifierID = [ruleComponents objectAtIndex:0]; + if ([self.dynamicSpecifiers objectForKey:opposingSpecifierID]) { + NSMutableArray *specifiers = [[self.dynamicSpecifiers objectForKey:opposingSpecifierID] mutableCopy]; + [specifiers addObject:specifier]; + + + [self.dynamicSpecifiers removeObjectForKey:opposingSpecifierID]; + [self.dynamicSpecifiers setObject:specifiers forKey:opposingSpecifierID]; + } else { + [self.dynamicSpecifiers setObject:[NSMutableArray arrayWithArray:@[specifier]] forKey:opposingSpecifierID]; + } + + } else { + [NSException raise:NSInternalInconsistencyException format:@"dynamicRule key requires three components (Specifier ID, Comparator, Value To Compare To). You have %ld of 3 (%@) for specifier '%@'.", ruleComponents.count, dynamicSpecifierRule, [specifier propertyForKey:PSTitleKey]]; + } + } + } + + self.hasDynamicSpecifiers = (self.dynamicSpecifiers.count > 0); } -(NSArray *)specifiers { @@ -145,23 +154,26 @@ 7. Next, in the `-tableView:heightForRowAtIndexPath:` delegate method we return zero whenever one of our dynamic specifiers should be hidden: ```objc --(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - if(self.hasDynamicSpecifiers) { - PSSpecifier *dynamicSpecifier = [self specifierAtIndexPath:indexPath]; - - if([self.dynamicSpecifiers.allValues containsObject:dynamicSpecifier]) { - BOOL shouldHide = [self shouldHideSpecifier:dynamicSpecifier]; - - UITableViewCell *specifierCell = [dynamicSpecifier propertyForKey:PSTableCellKey]; - specifierCell.clipsToBounds = shouldHide; - - if(shouldHide) { - return 0; - } +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + if (self.hasDynamicSpecifiers) { + PSSpecifier *dynamicSpecifier = [self specifierAtIndexPath:indexPath]; + BOOL __block shouldHide = false; + + [self.dynamicSpecifiers enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + NSMutableArray *specifiers = obj; + if ([specifiers containsObject:dynamicSpecifier]) { + shouldHide = [self shouldHideSpecifier:dynamicSpecifier]; + + UITableViewCell *specifierCell = [dynamicSpecifier propertyForKey:PSTableCellKey]; + specifierCell.clipsToBounds = shouldHide; + } + }]; + if (shouldHide) { + return 0; + } } - } - - return UITableViewAutomaticDimension; + + return UITableViewAutomaticDimension; } ```