Peter Warbo
Peter Warbo

Reputation: 11718

Objective-C – Profiling leaks shows Grand Central Dispatch is leaking

Could someone please help me spot the leak. I don't really know where my leak is. So I will post my code here and hopefully someone can spot it for me. In the leaks instrument it says responsible frame is dispatch_semaphore_create which I'm not calling?

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

        dispatch_group_t group = dispatch_group_create();

        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            if ([defaults boolForKey:@"notFirstRunSeminars"]) {

                BOOL isUpdated = self.seminarsParser.seminarsAreUpdated;

                if (isUpdated) {
                    DLog(@"Seminars have been updated");

                    [[NSNotificationCenter defaultCenter] 
                     postNotificationName:@"updateSeminarsTable" 
                     object:nil];

                    [[[[[self tabBarController] tabBar] items] objectAtIndex:kSeminarsTabIndex] setBadgeValue:self.seminarsParser.numberOfNewSeminars];
                    self.seminarsParser.numberOfNewSeminars = nil;

                }
            }
        });

        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            if ([defaults boolForKey:@"notFirstRunCareers"]) {

                BOOL isUpdated = self.careersParser.careersAreUpdated;

                if (isUpdated) {
                    DLog(@"Careers have been updated");

                    [[NSNotificationCenter defaultCenter] 
                     postNotificationName:@"updateCareersTable" 
                     object:nil];

                    [[[[[self tabBarController] tabBar] items] objectAtIndex:kCareersTabIndex] setBadgeValue:self.careersParser.numberOfNewCareers];
                    self.careersParser.numberOfNewCareers = nil;

                }
            }
        });

        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            if ([defaults boolForKey:@"notFirstRunOffices"]) {

                BOOL isUpdated = [officesParser officesAreUpdated];

                if (isUpdated) {
                    DLog(@"Offices have been updated");

                    [[NSNotificationCenter defaultCenter] 
                     postNotificationName:@"updateOfficesTable" 
                     object:nil];
                }
            }
        });

        dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];

        });

    });

Upvotes: 0

Views: 1265

Answers (2)

jkh
jkh

Reputation: 3266

Where are you releasing the group after you're done with it, since you're creating a group within the outermost async block? That's the only object I can see you creating which isn't being released properly. Incidently, a group creates a semaphore behind the scenes (all a dispatch group really is, is some syntactic sugar around an internal dispatch semaphore), which is why instruments is reporting it that way.

Upvotes: 1

justin
justin

Reputation: 104698

The zeroeth problem: What is being leaked?

Since I didn't see an obvious leak scanning your program, here's the most likely problem: UIKit objects are not threadsafe and only meant to be updated from the main thread, unless they enter your program from another thread.

Also note that NSNotifications are posted on the calling thread.

That means that all your UIKit type accesses and updates need to be performed on the main thread. And yes, that can introduce leaks or threading errors for which you should consider as undefined behaviour.

Upvotes: 3

Related Questions