LondonGuy
LondonGuy

Reputation: 11098

Should I be starting and stopping a UIActivityIndicator instance on the main thread?

Example:

[query findObjectsInBackgroundWithBlock:^(NSArray *favObjects, NSError *error) {
    for (PFObject *favObject in favObjects) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [cell setSizeLabel:[_arrayOfSizes objectAtIndex:[[favObject valueForKey:@"size"] integerValue]]];
            [[cell sizeDropDownButton] setTitle:[cell sizeLabel] forState:UIControlStateNormal];
        });

        if ([[[cell currentObject] valueForKey:@"alternativeColour"] boolValue]) {

            // Colours are stored in db on parse as numbers, I use array below to determine which colour is being red back by valueForkey below

            dispatch_async(dispatch_get_main_queue(), ^{
                [cell setColourLabel:[_arrayOfColours objectAtIndex:[[favObject valueForKey:@"colour"] integerValue]]];
                [[cell colourDropDownButton] setTitle:[cell colourLabel] forState:UIControlStateNormal];
            });
        }

        [[cell priceLabelSpinner] stopAnimating];
        [[cell titleLabelSpinner] stopAnimating];
        [[cell sizeDropDownButton] setHidden:NO];
        [[cell colourDropDownButton] setHidden:NO];

    }

}];

You can see I'm setting the the buttons label titles on the main queue. However below I'm stopping a the spinned on the background queue as well as unhiding buttons. Is this correct?

Upvotes: 0

Views: 73

Answers (3)

Hussain Shabbir
Hussain Shabbir

Reputation: 15015

As per Apple Documentation all UI updates should happen in main thread. So have modified your code and also include all UI updates in single dispatch_async block, try below:-

[query findObjectsInBackgroundWithBlock:^(NSArray *favObjects, NSError *error) {
    for (PFObject *favObject in favObjects) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [cell setSizeLabel:[_arrayOfSizes objectAtIndex:[[favObject valueForKey:@"size"] integerValue]]];
            [[cell sizeDropDownButton] setTitle:[cell sizeLabel] forState:UIControlStateNormal];
    if ([[[cell currentObject] valueForKey:@"alternativeColour"] boolValue]) {

        // Colours are stored in db on parse as numbers, I use array below to determine which colour is being red back by valueForkey below
            [cell setColourLabel:[_arrayOfColours objectAtIndex:[[favObject valueForKey:@"colour"] integerValue]]];
            [[cell colourDropDownButton] setTitle:[cell colourLabel] forState:UIControlStateNormal];

    }

    [[cell priceLabelSpinner] stopAnimating];
    [[cell titleLabelSpinner] stopAnimating];
    [[cell sizeDropDownButton] setHidden:NO];
    [[cell colourDropDownButton] setHidden:NO];

}

}];

Upvotes: 0

Keenle
Keenle

Reputation: 12200

Anything that can cause you view change should be called from main thread:

Manipulations to your application’s user interface must occur on the main thread. Thus, you should always call the methods of the UIView class from code running in the main thread of your application. The only time this may not be strictly necessary is when creating the view object itself but all other manipulations should occur on the main thread.

So taking into account what's suggested by Apple you should rewrite your code to:

[query findObjectsInBackgroundWithBlock:^(NSArray *favObjects, NSError *error) {
    for (PFObject *favObject in favObjects) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [cell setSizeLabel:[_arrayOfSizes objectAtIndex:[[favObject valueForKey:@"size"] integerValue]]];
            [[cell sizeDropDownButton] setTitle:[cell sizeLabel] forState:UIControlStateNormal];
        });

        if ([[[cell currentObject] valueForKey:@"alternativeColour"] boolValue]) {

            // Colours are stored in db on parse as numbers, I use array below to determine which colour is being red back by valueForkey below

            dispatch_async(dispatch_get_main_queue(), ^{
                [cell setColourLabel:[_arrayOfColours objectAtIndex:[[favObject valueForKey:@"colour"] integerValue]]];
                [[cell colourDropDownButton] setTitle:[cell colourLabel] forState:UIControlStateNormal];
            });
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            [[cell priceLabelSpinner] stopAnimating];
            [[cell titleLabelSpinner] stopAnimating];
            [[cell sizeDropDownButton] setHidden:NO];
            [[cell colourDropDownButton] setHidden:NO];
        });

    }

}];

Upvotes: 3

Timuçin
Timuçin

Reputation: 4673

Stopping animating or hiding views are also UI operations, so they must be done on main thread as well.

Upvotes: 2

Related Questions