IOS dispatch_async and for loop

1k Views Asked by At

I am trying to convert this code to do the for loop on a background thread because it is very slow and laggy as it is.

-(void)prepareLayout {
    [super prepareLayout];

    if (!_animator) {
    _animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self];
    CGSize contentSize = [self collectionViewContentSize];
    NSArray *items = [super layoutAttributesForElementsInRect:CGRectMake(0, 0, contentSize.width, contentSize.height)];
            for (UICollectionViewLayoutAttributes *item in items) {
                     UIAttachmentBehavior *spring = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:item.center];

                    spring.length = 0;
                    spring.damping = self.springDamping;
                    spring.frequency = self.springFrequency;

                    [_animator addBehavior:spring];

            }
}

}

I did try this but it doesn't work properly... It gets rid of the lag but some rows are missing or at weird positions in the collection view i thats coz the for loop isn't working properly with dispatch... -(void)prepareLayout { [super prepareLayout];

    if (!_animator) {
    _animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self];
    CGSize contentSize = [self collectionViewContentSize];
    NSArray *items = [super layoutAttributesForElementsInRect:CGRectMake(0, 0, contentSize.width, contentSize.height)];

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
    dispatch_async(queue, ^{
            for (UICollectionViewLayoutAttributes *item in items) {
                     UIAttachmentBehavior *spring = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:item.center];

                    spring.length = 0;
                    spring.damping = self.springDamping;
                    spring.frequency = self.springFrequency;

                    [_animator addBehavior:spring];
            }

           dispatch_sync(dispatch_get_main_queue(), ^{

           });
        });
    }
}

I have tried other variations but couldn't get it to work... would be great if someone could help me convert this code to run on a background thread properly... thank you

1

There are 1 best solutions below

0
On

There is no part of your prepareLayout that can safely be put on a background thread. UIKit elements must only be accessed on the main thread.

prepareLayout should not be called often enough that it could be causing your lag. If it is being called very often, you need to see why your layout is being invalidated so often.

If your collection view is very large (hundreds of items for instance), then your problem is likely that you're attaching too many items to behaviors. You should attach items to behaviors as they are created, and remove them as they are removed. UIKit Dynamics is not designed to manage hundreds or thousands of items.

Make sure to watch Advanced Techniques with UIKit Dynamics from WWDC 2013. I've found that combining UICollectionView and UIKit Dynamics is not obvious (start around page 110 in the slide deck). If you're not overriding layoutAttributesForElementsInRect:, then make sure to pay attention to that discussion.