XLFormDescriptor.m 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. //
  2. // XLFormDescriptor.m
  3. // XLForm ( https://github.com/xmartlabs/XLForm )
  4. //
  5. // Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
  6. //
  7. //
  8. // Permission is hereby granted, free of charge, to any person obtaining a copy
  9. // of this software and associated documentation files (the "Software"), to deal
  10. // in the Software without restriction, including without limitation the rights
  11. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. // copies of the Software, and to permit persons to whom the Software is
  13. // furnished to do so, subject to the following conditions:
  14. //
  15. // The above copyright notice and this permission notice shall be included in
  16. // all copies or substantial portions of the Software.
  17. //
  18. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. // THE SOFTWARE.
  25. #import "NSObject+XLFormAdditions.h"
  26. #import "XLFormDescriptor.h"
  27. #import "NSPredicate+XLFormAdditions.h"
  28. #import "NSString+XLFormAdditions.h"
  29. NSString * const XLFormErrorDomain = @"XLFormErrorDomain";
  30. NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
  31. @interface XLFormSectionDescriptor (_XLFormDescriptor)
  32. @property NSArray * allRows;
  33. -(BOOL)evaluateIsHidden;
  34. @end
  35. @interface XLFormRowDescriptor(_XLFormDescriptor)
  36. -(BOOL)evaluateIsDisabled;
  37. -(BOOL)evaluateIsHidden;
  38. @end
  39. @interface XLFormDescriptor()
  40. @property NSMutableArray * formSections;
  41. @property (readonly) NSMutableArray * allSections;
  42. @property NSString * title;
  43. @property (readonly) NSMutableDictionary* allRowsByTag;
  44. @property NSMutableDictionary* rowObservers;
  45. @end
  46. @implementation XLFormDescriptor
  47. -(instancetype)init
  48. {
  49. return [self initWithTitle:nil];
  50. }
  51. -(instancetype)initWithTitle:(NSString *)title;
  52. {
  53. self = [super init];
  54. if (self){
  55. _formSections = [NSMutableArray array];
  56. _allSections = [NSMutableArray array];
  57. _allRowsByTag = [NSMutableDictionary dictionary];
  58. _rowObservers = [NSMutableDictionary dictionary];
  59. _title = title;
  60. _addAsteriskToRequiredRowsTitle = NO;
  61. _disabled = NO;
  62. _endEditingTableViewOnScroll = YES;
  63. _rowNavigationOptions = XLFormRowNavigationOptionEnabled;
  64. [self addObserver:self forKeyPath:@"formSections" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:0];
  65. }
  66. return self;
  67. }
  68. +(instancetype)formDescriptor
  69. {
  70. return [[self class] formDescriptorWithTitle:nil];
  71. }
  72. +(instancetype)formDescriptorWithTitle:(NSString *)title
  73. {
  74. return [[[self class] alloc] initWithTitle:title];
  75. }
  76. -(void)addFormSection:(XLFormSectionDescriptor *)formSection
  77. {
  78. [self insertObject:formSection inAllSectionsAtIndex:[self.allSections count]];
  79. }
  80. -(void)addFormSection:(XLFormSectionDescriptor *)formSection atIndex:(NSUInteger)index
  81. {
  82. if (index == 0){
  83. [self insertObject:formSection inAllSectionsAtIndex:0];
  84. }
  85. else{
  86. XLFormSectionDescriptor* previousSection = [self.formSections objectAtIndex:MIN(self.formSections.count, index-1)];
  87. [self addFormSection:formSection afterSection:previousSection];
  88. }
  89. }
  90. -(void)addFormSection:(XLFormSectionDescriptor *)formSection afterSection:(XLFormSectionDescriptor *)afterSection
  91. {
  92. NSUInteger sectionIndex;
  93. NSUInteger allSectionIndex;
  94. if ((sectionIndex = [self.allSections indexOfObject:formSection]) == NSNotFound){
  95. allSectionIndex = [self.allSections indexOfObject:afterSection];
  96. if (allSectionIndex != NSNotFound) {
  97. [self insertObject:formSection inAllSectionsAtIndex:(allSectionIndex + 1)];
  98. }
  99. else { //case when afterSection does not exist. Just insert at the end.
  100. [self addFormSection:formSection];
  101. return;
  102. }
  103. }
  104. formSection.hidden = formSection.hidden;
  105. }
  106. -(void)addFormRow:(XLFormRowDescriptor *)formRow beforeRow:(XLFormRowDescriptor *)beforeRow
  107. {
  108. if (beforeRow.sectionDescriptor){
  109. [beforeRow.sectionDescriptor addFormRow:formRow beforeRow:beforeRow];
  110. }
  111. else{
  112. [[self.allSections lastObject] addFormRow:formRow beforeRow:beforeRow];
  113. }
  114. }
  115. -(void)addFormRow:(XLFormRowDescriptor *)formRow beforeRowTag:(NSString *)beforeRowTag
  116. {
  117. XLFormRowDescriptor * beforeRowForm = [self formRowWithTag:beforeRowTag];
  118. [self addFormRow:formRow beforeRow:beforeRowForm];
  119. }
  120. -(void)addFormRow:(XLFormRowDescriptor *)formRow afterRow:(XLFormRowDescriptor *)afterRow
  121. {
  122. if (afterRow.sectionDescriptor){
  123. [afterRow.sectionDescriptor addFormRow:formRow afterRow:afterRow];
  124. }
  125. else{
  126. [[self.allSections lastObject] addFormRow:formRow afterRow:afterRow];
  127. }
  128. }
  129. -(void)addFormRow:(XLFormRowDescriptor *)formRow afterRowTag:(NSString *)afterRowTag
  130. {
  131. XLFormRowDescriptor * afterRowForm = [self formRowWithTag:afterRowTag];
  132. [self addFormRow:formRow afterRow:afterRowForm];
  133. }
  134. -(void)removeFormSectionAtIndex:(NSUInteger)index
  135. {
  136. if (self.formSections.count > index){
  137. XLFormSectionDescriptor *formSection = [self.formSections objectAtIndex:index];
  138. [self removeObjectFromFormSectionsAtIndex:index];
  139. NSUInteger allSectionIndex = [self.allSections indexOfObject:formSection];
  140. [self removeObjectFromAllSectionsAtIndex:allSectionIndex];
  141. }
  142. }
  143. -(void)removeFormSection:(XLFormSectionDescriptor *)formSection
  144. {
  145. NSUInteger index = NSNotFound;
  146. if ((index = [self.formSections indexOfObject:formSection]) != NSNotFound){
  147. [self removeFormSectionAtIndex:index];
  148. }
  149. else if ((index = [self.allSections indexOfObject:formSection]) != NSNotFound){
  150. [self removeObjectFromAllSectionsAtIndex:index];
  151. };
  152. }
  153. -(void)removeFormRow:(XLFormRowDescriptor *)formRow
  154. {
  155. for (XLFormSectionDescriptor * section in self.formSections){
  156. if ([section.formRows containsObject:formRow]){
  157. [section removeFormRow:formRow];
  158. }
  159. }
  160. }
  161. -(void)showFormSection:(XLFormSectionDescriptor*)formSection
  162. {
  163. NSUInteger formIndex = [self.formSections indexOfObject:formSection];
  164. if (formIndex != NSNotFound) {
  165. return;
  166. }
  167. NSUInteger index = [self.allSections indexOfObject:formSection];
  168. if (index != NSNotFound){
  169. while (formIndex == NSNotFound && index > 0) {
  170. XLFormSectionDescriptor* previous = [self.allSections objectAtIndex:--index];
  171. formIndex = [self.formSections indexOfObject:previous];
  172. }
  173. [self insertObject:formSection inFormSectionsAtIndex:(formIndex == NSNotFound ? 0 : ++formIndex)];
  174. }
  175. }
  176. -(void)hideFormSection:(XLFormSectionDescriptor*)formSection
  177. {
  178. NSUInteger index = [self.formSections indexOfObject:formSection];
  179. if (index != NSNotFound){
  180. [self removeObjectFromFormSectionsAtIndex:index];
  181. }
  182. }
  183. -(XLFormRowDescriptor *)formRowWithTag:(NSString *)tag
  184. {
  185. return self.allRowsByTag[tag];
  186. }
  187. -(XLFormRowDescriptor *)formRowWithHash:(NSUInteger)hash
  188. {
  189. for (XLFormSectionDescriptor * section in self.allSections){
  190. for (XLFormRowDescriptor * row in section.allRows) {
  191. if ([row hash] == hash){
  192. return row;
  193. }
  194. }
  195. }
  196. return nil;
  197. }
  198. -(void)removeFormRowWithTag:(NSString *)tag
  199. {
  200. XLFormRowDescriptor * formRow = [self formRowWithTag:tag];
  201. [self removeFormRow:formRow];
  202. }
  203. -(XLFormRowDescriptor *)formRowAtIndex:(NSIndexPath *)indexPath
  204. {
  205. if ((self.formSections.count > indexPath.section) && [[self.formSections objectAtIndex:indexPath.section] formRows].count > indexPath.row){
  206. return [[[self.formSections objectAtIndex:indexPath.section] formRows] objectAtIndex:indexPath.row];
  207. }
  208. return nil;
  209. }
  210. -(XLFormSectionDescriptor *)formSectionAtIndex:(NSUInteger)index
  211. {
  212. return [self objectInFormSectionsAtIndex:index];
  213. }
  214. -(NSIndexPath *)indexPathOfFormRow:(XLFormRowDescriptor *)formRow
  215. {
  216. XLFormSectionDescriptor * section = formRow.sectionDescriptor;
  217. if (section){
  218. NSUInteger sectionIndex = [self.formSections indexOfObject:section];
  219. if (sectionIndex != NSNotFound){
  220. NSUInteger rowIndex = [section.formRows indexOfObject:formRow];
  221. if (rowIndex != NSNotFound){
  222. return [NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex];
  223. }
  224. }
  225. }
  226. return nil;
  227. }
  228. -(NSIndexPath *)globalIndexPathOfFormRow:(XLFormRowDescriptor *)formRow
  229. {
  230. XLFormSectionDescriptor * section = formRow.sectionDescriptor;
  231. if (section){
  232. NSUInteger sectionIndex = [self.allSections indexOfObject:section];
  233. if (sectionIndex != NSNotFound){
  234. NSUInteger rowIndex = [section.allRows indexOfObject:formRow];
  235. if (rowIndex != NSNotFound){
  236. return [NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex];
  237. }
  238. }
  239. }
  240. return nil;
  241. }
  242. -(NSDictionary *)formValues
  243. {
  244. NSMutableDictionary * result = [NSMutableDictionary dictionary];
  245. for (XLFormSectionDescriptor * section in self.formSections) {
  246. if (section.multivaluedTag.length > 0){
  247. NSMutableArray * multiValuedValuesArray = [NSMutableArray new];
  248. for (XLFormRowDescriptor * row in section.formRows) {
  249. if (row.value){
  250. [multiValuedValuesArray addObject:row.value];
  251. }
  252. }
  253. [result setObject:multiValuedValuesArray forKey:section.multivaluedTag];
  254. }
  255. else{
  256. for (XLFormRowDescriptor * row in section.formRows) {
  257. if (row.tag.length > 0){
  258. [result setObject:(row.value ?: [NSNull null]) forKey:row.tag];
  259. }
  260. }
  261. }
  262. }
  263. return result;
  264. }
  265. -(NSDictionary *)httpParameters:(XLFormViewController *)formViewController
  266. {
  267. NSMutableDictionary * result = [NSMutableDictionary dictionary];
  268. for (XLFormSectionDescriptor * section in self.formSections) {
  269. if (section.multivaluedTag.length > 0){
  270. NSMutableArray * multiValuedValuesArray = [NSMutableArray new];
  271. for (XLFormRowDescriptor * row in section.formRows) {
  272. if ([row.value valueData]){
  273. [multiValuedValuesArray addObject:[row.value valueData]];
  274. }
  275. }
  276. [result setObject:multiValuedValuesArray forKey:section.multivaluedTag];
  277. }
  278. else{
  279. for (XLFormRowDescriptor * row in section.formRows) {
  280. NSString * httpParameterKey = nil;
  281. if ((httpParameterKey = [self httpParameterKeyForRow:row cell:[row cellForFormController:formViewController]])){
  282. id parameterValue = [row.value valueData] ?: [NSNull null];
  283. [result setObject:parameterValue forKey:httpParameterKey];
  284. }
  285. }
  286. }
  287. }
  288. return result;
  289. }
  290. -(NSString *)httpParameterKeyForRow:(XLFormRowDescriptor *)row cell:(UITableViewCell<XLFormDescriptorCell> *)descriptorCell
  291. {
  292. if ([descriptorCell respondsToSelector:@selector(formDescriptorHttpParameterName)]){
  293. return [descriptorCell formDescriptorHttpParameterName];
  294. }
  295. if (row.tag.length > 0){
  296. return row.tag;
  297. }
  298. return nil;
  299. }
  300. -(NSArray *)localValidationErrors:(XLFormViewController *)formViewController {
  301. NSMutableArray * result = [NSMutableArray array];
  302. for (XLFormSectionDescriptor * section in self.formSections) {
  303. for (XLFormRowDescriptor * row in section.formRows) {
  304. XLFormValidationStatus* status = [row doValidation];
  305. if (status != nil && (![status isValid])) {
  306. NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: status.msg,
  307. XLValidationStatusErrorKey: status };
  308. NSError * error = [[NSError alloc] initWithDomain:XLFormErrorDomain code:XLFormErrorCodeGen userInfo:userInfo];
  309. if (error){
  310. [result addObject:error];
  311. }
  312. }
  313. }
  314. }
  315. return result;
  316. }
  317. - (void)setFirstResponder:(XLFormViewController *)formViewController
  318. {
  319. for (XLFormSectionDescriptor * formSection in self.formSections) {
  320. for (XLFormRowDescriptor * row in formSection.formRows) {
  321. UITableViewCell<XLFormDescriptorCell> * cell = [row cellForFormController:formViewController];
  322. if ([cell formDescriptorCellCanBecomeFirstResponder]){
  323. if ([cell formDescriptorCellBecomeFirstResponder]){
  324. return;
  325. }
  326. }
  327. }
  328. }
  329. }
  330. #pragma mark - KVO
  331. -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
  332. {
  333. if (!self.delegate) return;
  334. if ([keyPath isEqualToString:@"formSections"]){
  335. if ([[change objectForKey:NSKeyValueChangeKindKey] isEqualToNumber:@(NSKeyValueChangeInsertion)]){
  336. NSIndexSet * indexSet = [change objectForKey:NSKeyValueChangeIndexesKey];
  337. XLFormSectionDescriptor * section = [self.formSections objectAtIndex:indexSet.firstIndex];
  338. [self.delegate formSectionHasBeenAdded:section atIndex:indexSet.firstIndex];
  339. }
  340. else if ([[change objectForKey:NSKeyValueChangeKindKey] isEqualToNumber:@(NSKeyValueChangeRemoval)]){
  341. NSIndexSet * indexSet = [change objectForKey:NSKeyValueChangeIndexesKey];
  342. XLFormSectionDescriptor * removedSection = [[change objectForKey:NSKeyValueChangeOldKey] objectAtIndex:0];
  343. [self.delegate formSectionHasBeenRemoved:removedSection atIndex:indexSet.firstIndex];
  344. }
  345. }
  346. }
  347. -(void)dealloc
  348. {
  349. @try {
  350. [self removeObserver:self forKeyPath:@"formSections"];
  351. }
  352. @catch (NSException * __unused exception) {}
  353. }
  354. #pragma mark - KVC
  355. -(NSUInteger)countOfFormSections
  356. {
  357. return self.formSections.count;
  358. }
  359. - (id)objectInFormSectionsAtIndex:(NSUInteger)index {
  360. return [self.formSections objectAtIndex:index];
  361. }
  362. - (NSArray *)formSectionsAtIndexes:(NSIndexSet *)indexes {
  363. return [self.formSections objectsAtIndexes:indexes];
  364. }
  365. - (void)insertObject:(XLFormSectionDescriptor *)formSection inFormSectionsAtIndex:(NSUInteger)index {
  366. [self.formSections insertObject:formSection atIndex:index];
  367. }
  368. - (void)removeObjectFromFormSectionsAtIndex:(NSUInteger)index {
  369. [self.formSections removeObjectAtIndex:index];
  370. }
  371. #pragma mark - allSections KVO
  372. -(NSUInteger)countOfAllSections
  373. {
  374. return self.allSections.count;
  375. }
  376. - (id)objectInAllSectionsAtIndex:(NSUInteger)index {
  377. return [self.allSections objectAtIndex:index];
  378. }
  379. - (NSArray *)allSectionsAtIndexes:(NSIndexSet *)indexes {
  380. return [self.allSections objectsAtIndexes:indexes];
  381. }
  382. - (void)removeObjectFromAllSectionsAtIndex:(NSUInteger)index {
  383. XLFormSectionDescriptor* section = [self.allSections objectAtIndex:index];
  384. [section.allRows enumerateObjectsUsingBlock:^(id obj, NSUInteger __unused idx, BOOL *stop) {
  385. XLFormRowDescriptor * row = (id)obj;
  386. [self removeObserversOfObject:row predicateType:XLPredicateTypeDisabled];
  387. [self removeObserversOfObject:row predicateType:XLPredicateTypeHidden];
  388. }];
  389. [self removeObserversOfObject:section predicateType:XLPredicateTypeHidden];
  390. [self.allSections removeObjectAtIndex:index];
  391. }
  392. - (void)insertObject:(XLFormSectionDescriptor *)section inAllSectionsAtIndex:(NSUInteger)index {
  393. section.formDescriptor = self;
  394. [self.allSections insertObject:section atIndex:index];
  395. section.hidden = section.hidden;
  396. [section.allRows enumerateObjectsUsingBlock:^(id obj, NSUInteger __unused idx, BOOL * __unused stop) {
  397. XLFormRowDescriptor * row = (id)obj;
  398. [self addRowToTagCollection:obj];
  399. row.hidden = row.hidden;
  400. row.disabled = row.disabled;
  401. }];
  402. }
  403. #pragma mark - EvaluateForm
  404. -(void)forceEvaluate
  405. {
  406. for (XLFormSectionDescriptor* section in self.allSections){
  407. for (XLFormRowDescriptor* row in section.allRows) {
  408. [self addRowToTagCollection:row];
  409. }
  410. }
  411. for (XLFormSectionDescriptor* section in self.allSections){
  412. for (XLFormRowDescriptor* row in section.allRows) {
  413. [row evaluateIsDisabled];
  414. [row evaluateIsHidden];
  415. }
  416. [section evaluateIsHidden];
  417. }
  418. }
  419. #pragma mark - private
  420. -(NSMutableArray *)formSections
  421. {
  422. return _formSections;
  423. }
  424. #pragma mark - Helpers
  425. -(XLFormRowDescriptor *)nextRowDescriptorForRow:(XLFormRowDescriptor *)row
  426. {
  427. NSUInteger indexOfRow = [row.sectionDescriptor.formRows indexOfObject:row];
  428. if (indexOfRow != NSNotFound){
  429. if (indexOfRow + 1 < row.sectionDescriptor.formRows.count){
  430. return [row.sectionDescriptor.formRows objectAtIndex:++indexOfRow];
  431. }
  432. else{
  433. NSUInteger sectionIndex = [self.formSections indexOfObject:row.sectionDescriptor];
  434. NSUInteger numberOfSections = [self.formSections count];
  435. if (sectionIndex != NSNotFound && sectionIndex < numberOfSections - 1){
  436. sectionIndex++;
  437. XLFormSectionDescriptor * sectionDescriptor;
  438. while ([[(sectionDescriptor = [row.sectionDescriptor.formDescriptor.formSections objectAtIndex:sectionIndex]) formRows] count] == 0 && sectionIndex < numberOfSections - 1){
  439. sectionIndex++;
  440. }
  441. return [sectionDescriptor.formRows firstObject];
  442. }
  443. }
  444. }
  445. return nil;
  446. }
  447. -(XLFormRowDescriptor *)previousRowDescriptorForRow:(XLFormRowDescriptor *)row
  448. {
  449. NSUInteger indexOfRow = [row.sectionDescriptor.formRows indexOfObject:row];
  450. if (indexOfRow != NSNotFound){
  451. if (indexOfRow > 0 ){
  452. return [row.sectionDescriptor.formRows objectAtIndex:--indexOfRow];
  453. }
  454. else{
  455. NSUInteger sectionIndex = [self.formSections indexOfObject:row.sectionDescriptor];
  456. if (sectionIndex != NSNotFound && sectionIndex > 0){
  457. sectionIndex--;
  458. XLFormSectionDescriptor * sectionDescriptor;
  459. while ([[(sectionDescriptor = [row.sectionDescriptor.formDescriptor.formSections objectAtIndex:sectionIndex]) formRows] count] == 0 && sectionIndex > 0 ){
  460. sectionIndex--;
  461. }
  462. return [sectionDescriptor.formRows lastObject];
  463. }
  464. }
  465. }
  466. return nil;
  467. }
  468. -(void)addRowToTagCollection:(XLFormRowDescriptor*) rowDescriptor
  469. {
  470. if (rowDescriptor.tag) {
  471. self.allRowsByTag[rowDescriptor.tag] = rowDescriptor;
  472. }
  473. }
  474. -(void)removeRowFromTagCollection:(XLFormRowDescriptor *)rowDescriptor
  475. {
  476. if (rowDescriptor.tag){
  477. [self.allRowsByTag removeObjectForKey:rowDescriptor.tag];
  478. }
  479. }
  480. -(void)addObserversOfObject:(id)sectionOrRow predicateType:(XLPredicateType)predicateType
  481. {
  482. NSPredicate* predicate;
  483. id descriptor;
  484. switch(predicateType){
  485. case XLPredicateTypeHidden:
  486. if ([sectionOrRow isKindOfClass:([XLFormRowDescriptor class])]) {
  487. descriptor = ((XLFormRowDescriptor*)sectionOrRow).tag;
  488. predicate = ((XLFormRowDescriptor*)sectionOrRow).hidden;
  489. }
  490. else if ([sectionOrRow isKindOfClass:([XLFormSectionDescriptor class])]) {
  491. descriptor = sectionOrRow;
  492. predicate = ((XLFormSectionDescriptor*)sectionOrRow).hidden;
  493. }
  494. break;
  495. case XLPredicateTypeDisabled:
  496. if ([sectionOrRow isKindOfClass:([XLFormRowDescriptor class])]) {
  497. descriptor = ((XLFormRowDescriptor*)sectionOrRow).tag;
  498. predicate = ((XLFormRowDescriptor*)sectionOrRow).disabled;
  499. }
  500. else return;
  501. break;
  502. }
  503. NSMutableArray* tags = [predicate getPredicateVars];
  504. for (NSString* tag in tags) {
  505. NSString* auxTag = [tag formKeyForPredicateType:predicateType];
  506. if (!self.rowObservers[auxTag]){
  507. self.rowObservers[auxTag] = [NSMutableArray array];
  508. }
  509. if (![self.rowObservers[auxTag] containsObject:descriptor])
  510. [self.rowObservers[auxTag] addObject:descriptor];
  511. }
  512. }
  513. -(void)removeObserversOfObject:(id)sectionOrRow predicateType:(XLPredicateType)predicateType
  514. {
  515. NSPredicate* predicate;
  516. id descriptor;
  517. switch(predicateType){
  518. case XLPredicateTypeHidden:
  519. if ([sectionOrRow isKindOfClass:([XLFormRowDescriptor class])]) {
  520. descriptor = ((XLFormRowDescriptor*)sectionOrRow).tag;
  521. predicate = ((XLFormRowDescriptor*)sectionOrRow).hidden;
  522. }
  523. else if ([sectionOrRow isKindOfClass:([XLFormSectionDescriptor class])]) {
  524. descriptor = sectionOrRow;
  525. predicate = ((XLFormSectionDescriptor*)sectionOrRow).hidden;
  526. }
  527. break;
  528. case XLPredicateTypeDisabled:
  529. if ([sectionOrRow isKindOfClass:([XLFormRowDescriptor class])]) {
  530. descriptor = ((XLFormRowDescriptor*)sectionOrRow).tag;
  531. predicate = ((XLFormRowDescriptor*)sectionOrRow).disabled;
  532. }
  533. break;
  534. }
  535. if (descriptor && [predicate isKindOfClass:[NSPredicate class] ]) {
  536. NSMutableArray* tags = [predicate getPredicateVars];
  537. for (NSString* tag in tags) {
  538. NSString* auxTag = [tag formKeyForPredicateType:predicateType];
  539. if (self.rowObservers[auxTag]){
  540. [self.rowObservers[auxTag] removeObject:descriptor];
  541. }
  542. }
  543. }
  544. }
  545. @end