0

I have a unique case where I need to populate a menu with thousands of items from an sqlite database...

I am currently filling it with the following code, but it blocks the main thread while its populating, and takes upwards of a minute to load (the first time) as it fills with ~3000 items. Is there an effective way to lazy load the menu in smaller chunks without blocking the ui?

rules.h

{
    IBOutlet NSPopUpButton *rulesSelectionButton;
}
@property (retain) IBOutlet NSPopUpButton *rulesSelectionButton;

rules.m

@synthesize rulesSelectionButton;

and the code to populate the button:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *selected = [defaults objectForKey:rulesSelectionString];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    NSString *path = [dbPath stringByExpandingTildeInPath];
    __block NSArray *final = [NSArray new];

    FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
    [queue inDatabase:^(FMDatabase *db) {
        FMResultSet *results = [db executeQuery:@"SELECT * FROM rules"];
        NSMutableArray *array = [NSMutableArray new];
        [array addObject:NSLocalizedString(@"Random...", nil)];

        while ([results next]) {
            @autoreleasepool {
                NSString *title = [NSString stringWithFormat:@"%@ (%@)", [results stringForColumn:@"Organization_Rules"], [results stringForColumn:@"Assignment"]];
                [array addObject:title];
            }
        }
        final = [[NSSet setWithArray:array] allObjects];
    }];

    NSArray *sortedKeys = [final sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
    dispatch_async(dispatch_get_main_queue(), ^{

        [rulesSelectionButton removeAllItems];
        [rulesSelectionButton addItemsWithTitles:sortedKeys];
        [rulesSelectionButton selectItemWithTitle:selected];
    });
});
gypsyDev
  • 1,232
  • 1
  • 14
  • 22
  • I don't see a single word 'NSPopUpButton' in your code. It would be a bad idea to create thousands of menu items, anyway. – El Tomato Dec 09 '16 at 22:29
  • rulesSelectionButton is a property, i added the relevant code.it may well be a bad idea to put thousands of menu items into a menu, but I still need to do it, as its the best way of presenting the data. – gypsyDev Dec 09 '16 at 23:36
  • I don't think it's the best way of presenting the data because NSPopUpButton isn't designed to hande thousands of items. Apple says "Use a pop-up menu to present up to 12 mutually exclusive choices that users don’t need to see all the time." and "Consider using a scrolling list, instead of a pop-up menu, for a large number of items." – Willeke Dec 10 '16 at 00:26
  • thanks guys, I found that NSComboBox does all I want, and loads super quick. :) – gypsyDev Dec 11 '16 at 01:03

1 Answers1

0

NSComboBox is a much better fit for a huge list of items, and is actually a lot easier to setup than an NSPopupBotton... although it doesn't look as nice.

gypsyDev
  • 1,232
  • 1
  • 14
  • 22