InAppSettingsKit icon indicating copy to clipboard operation
InAppSettingsKit copied to clipboard

calling sethiddenkeys from within kIASKAppSettingChanged call crashes app

Open mournblade opened this issue 2 years ago • 1 comments

I had an old issue with this that seems to be back for me. (old issue): https://github.com/futuretap/InAppSettingsKit/issues/289

consider this method:

  • (void)updateVisibilityItems { NSMutableSet *set = CacheHandler.cache.isAdminOrManager ? [NSMutableSet set] : [NSMutableSet setWithArray:@[@"push_notifications", @"com.a.STATUS", @"accAlarmNot", @"accAlarmNotHeader", @"accEmail", @"accEmailHeader"]];

    if (([prefs getCheckingInGeofenceActionType] == OFF)) { [set addObject:@"geoChangePolicyGrp"]; } [self setHiddenKeys:set animated:true];//CRASHES IF FALSE DebugLog(@"updateVisibilityItems"); }

if I call this when my kIASKAppSettingChanged observer method is called, it crashes if animated is false. Version 3.4

The error I get is:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (1) must be equal to the number of sections contained in the table view before the update (2), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).

mournblade avatar Oct 10 '23 12:10 mournblade

Can you provide a demo project exhibiting the issue?

futuretap avatar Oct 25 '23 20:10 futuretap

@mournblade

  1. It's good practise to embed code snippets in a code block at GitHub, so contributors have proper syntax highlighting:
- (void)updateVisibilityItems {
NSMutableSet *set = CacheHandler.cache.isAdminOrManager ? [NSMutableSet set] : [NSMutableSet setWithArray:@[@"push_notifications", @"com.a.STATUS", @"accAlarmNot", @"accAlarmNotHeader", @"accEmail", @"accEmailHeader"]];

if (([prefs getCheckingInGeofenceActionType] == OFF)) {
    [set addObject:@"geoChangePolicyGrp"];
}

[self setHiddenKeys:set animated:true];//CRASHES IF FALSE
DebugLog(@"updateVisibilityItems");
}
  1. In ObjectiveC, booleans are YES and NO instead of true and FALSE

  2. It's good practice to call any updates of the view on the main thread via dispatch_async(). In my code I have the following callback for settingDidChange: which setHiddenKeys: successfully with both animated: at YES and NO:

- (void)settingDidChange:(NSNotification *)notification {
    NSDictionary *data = [notification userInfo];
    NSLog(@"settingDidChange for property: %@", data);
    
    if ([data count] > 0) {
        // Get setting key:
        NSString *key = [[data allKeys] firstObject];
        
        if ([key isEqualToString:"someKey"]) {            
            // Update UI on main thread:
            dispatch_async(dispatch_get_main_queue(), ^{
                // Update dynamic cell hiding with animation:
                [self setHiddenKeys:[self getHiddenCellsForSettings]
                           animated:YES];
            });
        }
    }
}

Based on this, your code should be:

- (void)updateVisibilityItems {
NSMutableSet *set = CacheHandler.cache.isAdminOrManager ? [NSMutableSet set] : [NSMutableSet setWithArray:@[@"push_notifications", @"com.a.STATUS", @"accAlarmNot", @"accAlarmNotHeader", @"accEmail", @"accEmailHeader"]];

if (([prefs getCheckingInGeofenceActionType] == OFF)) {
    [set addObject:@"geoChangePolicyGrp"];
}

// Update UI on main thread:
dispatch_async(dispatch_get_main_queue(), ^{
    [self setHiddenKeys:set animated:NO];
});
DebugLog(@"updateVisibilityItems");
}

Please try this and report your findings.

funnel20 avatar Sep 27 '24 08:09 funnel20