Search code examples
objective-cnsarraynsdictionary

Executing method of a class multiple times parallel


I have an array- say wordsArray where each object of wordArray is another array- say wordList. With for loop i am picking each object (wordList) and call a method -say wordScore of another class which will return NSDictionary with word and the score. Instead of calling wordScore for each object one by one, Is there a way I can run them parallel? wordScore for each wordList should execute in parallel and at the end of execution all the NSDictionaries of each wordScore should be merged into a single NSDictionary.


Solution

  • Let's say I have something silly like this class

    @interface MyWordClass: NSObject
    - (NSDictionary *)wordScore:(NSArray *)wordList;
    @end
    
    @implementation MyWordClass
    - (NSDictionary *)wordScore:(NSArray *)wordList {
        NSMutableDictionary *scores = [NSMutableDictionary new];
        for (NSString *word in wordList) {
            scores[word] = @(word.hash %100);
        }
        return [scores copy];
    }
    @end
    

    From here, I'll do a concurrent enumeration of wordsArray. I create a new instance of MyWordClass in each of the concurrent iterations. Finally, I use a @synchronized block to accumulate the results.

    NSArray *wordsArray = @[@[@"a", @"b", @"c"], @[@"1", @"2", @"3"]];
    
    NSMutableDictionary *result = [NSMutableDictionary new];
    [wordsArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSArray *wordList, NSUInteger idx, BOOL *stop) {
        // The scores are being calculated concurrently
        NSDictionary *scores = [[MyWordClass new] wordScore:wordList];
    
        @synchronized(result) {
            [result addEntriesFromDictionary:scores];
        }
    }];
    
    NSLog(@"%@", result);
    

    Important take aways are 1) do a concurrent enumeration, 2) don't use shared instances in the concurrent block, and 3) use a @synchronized block to gather the result.