-
-
Notifications
You must be signed in to change notification settings - Fork 143
NSInternalInconsistency exception when attempting to process FORMTarget #582
Description
Hi,
The Issue
I am trying to automate the process of filling form field data based on data present in other fields. Basically, implement a rules engine of sorts into forms. For example, if a checkbox gets checked, it'll hide a specific field further down the line, and vice versa if it's unchecked.
The logic behind this is already fleshed out, and functional, but only when the form isn't too big so that there are non-visible fields. I.e., if there's fields at the bottom of the form that one has yet to scroll through, and I attempt to update any field (visible or otherwise) through the use of FORMTargets, a NSInternalInconsistency exception is thrown. That the number of items before the update must be equal to after the update plus or minus the modifications.
The Code
Attached you will find a very simple json to demo this on, as of this writing (August 21st, 2017), I am on the latest version of the engine, and am using the demo HYPSampleCollectionViewController from the Basic-ObjC scheme, I am just swapping out the filename.
- (void)checkRules { FORMField *field = [self.dataSource fieldWithID:@"check" includingHiddenFields:YES]; NSMutableArray *targets = [NSMutableArray array];
if ([field.value boolValue])
{
[targets addObject:[FORMTarget hideFieldTargetWithID:@"adult_dates"]];
[targets addObject:[FORMTarget showFieldTargetWithID:@"juvenile"]];
}
else
{
[targets addObject:[FORMTarget hideFieldTargetWithID:@"juvenile"]];
[targets addObject:[FORMTarget showFieldTargetWithID:@"adult_dates"]];
}
field = [self.dataSource fieldWithID:@"choice" includingHiddenFields:YES];
FORMFieldValue *value = field.value;
if ([value.value isEqualToNumber:@0])
{
FORMTarget *target1 = [FORMTarget updateFieldTargetWithID:@"male"];
target1.targetValue = @YES;
FORMTarget *target2 = [FORMTarget updateFieldTargetWithID:@"female"];
target2.targetValue = @NO;
[targets addObject:target1];
[targets addObject:target2];
}
else if ([value.value isEqualToNumber:@1])
{
FORMTarget *target1 = [FORMTarget updateFieldTargetWithID:@"female"];
target1.targetValue = @YES;
FORMTarget *target2 = [FORMTarget updateFieldTargetWithID:@"male"];
target2.targetValue = @NO;
[targets addObject:target1];
[targets addObject:target2];
}
[self.dataSource processTargets:targets];
}
Above is the code I use to check the current field values and generate targets accordingly. This is called in every field's fieldUpdatedBlock.
So yeah, as mentioned, the code does work, it's just that when there's fields out of view that the number of items somehow gets corrupted after/while processing the targets. If I modify my json to only have one group, so that it can all fit on the screen without having to scroll, then there are no issues.
For example, here is the exception logged when attempting to toggle the "Is Juvenile?" switch:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (4) must be equal to the number of items contained in that section before the update (4), plus or minus the number of items inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).' *** First throw call stack:
0 CoreFoundation 0x00000001014c5b0b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x0000000100f2a141 objc_exception_throw + 48
2 CoreFoundation 0x00000001014c9cf2 +[NSException raise:format:arguments:] + 98
3 Foundation 0x0000000100ac43b6 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 193
4 UIKit 0x000000010291d9f2 -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:] + 16569
5 UIKit 0x000000010291975a -[UICollectionView _updateRowsAtIndexPaths:updateAction:] + 372
6 Form 0x000000010080ba49 -[FORMDataSource deleteItemsAtIndexPaths:] + 153
7 Form 0x0000000100812599 __33-[FORMDataSource processTargets:]_block_invoke + 825
8 Form 0x0000000100839acf +[FORMTarget filteredTargets:filtered:] + 1199
9 Form 0x0000000100812230 -[FORMDataSource processTargets:] + 160
10 Basic-ObjC 0x0000000100752151 -[HYPSampleCollectionViewController checkRules] + 1953
11 Basic-ObjC 0x00000001007500a8 __52-[HYPSampleCollectionViewController setUpDataSource]_block_invoke_2 + 648
12 Form 0x0000000100810dd3 -[FORMDataSource fieldCell:updatedWithField:] + 195
13 Form 0x0000000100836695 -[FORMSwitchFieldCell switchAction:] + 469`
Thank you in advance for any insight you could provide.