Skip to content
This repository was archived by the owner on Mar 7, 2021. It is now read-only.

NSInternalInconsistency exception when attempting to process FORMTarget #582

Open
mmarbouh opened this issue Aug 21, 2017 · 1 comment
Open

Comments

@mmarbouh
Copy link

mmarbouh commented Aug 21, 2017

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

data.json.txt

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.

@3lvis
Copy link
Owner

3lvis commented Aug 22, 2017

Hi @mmarbouh, I was trying to reproduce your issue but got a bit confused, also the JSON that you provided doesn't work out of the box with the demo project since it needs a few custom fields. Could you please provide a sample project that shows the problem?

Thanks in advance :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants