4

I wanted to know why my code runs much slower when I use dispatch_async compared to when I don't use it at all. I'm trying to blur the edges of my UIImage by masking it and using UIGraphicsImageRenderer (Not sure if it's the most efficient way or not..)But when I don't use dispatch_async, It runs much much faster. Why is that? Here is my code and the result I get from my code. Any help is muchhhhh appreciated.

enter image description here

self.view.backgroundColor = [UIColor whiteColor];
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                UIImage* Img =  [UIImage imageNamed:@"1"];
                UIImageView * imageview = [[UIImageView alloc]initWithImage:Img];
                UIGraphicsImageRenderer * renderer = [[UIGraphicsImageRenderer alloc] initWithSize:Img.size];

                UIBezierPath*path=[UIBezierPath bezierPathWithRoundedRect:CGRectMake(20,20,170,170) cornerRadius:5.0];
                path.lineWidth = 20;

                CAShapeLayer*shapeLayer = [CAShapeLayer new];
                shapeLayer.path=path.CGPath;

                [shapeLayer setFillColor:[UIColor redColor].CGColor];
                [shapeLayer fillColor];

                UIImage *shapeImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull context){
                    [shapeLayer renderInContext: context.CGContext];}];

                CIImage * shapeCimage = [[CIImage alloc] initWithImage:shapeImage];
                CIFilter * gaussianBlurFilter = [CIFilter filterWithName: @"CIGaussianBlur"];
                [gaussianBlurFilter setValue:shapeCimage forKey: @"inputImage"];
                [gaussianBlurFilter setValue:@15 forKey:@"inputRadius"];

                CIImage * blurredCIImage = [gaussianBlurFilter valueForKey:kCIOutputImageKey];
                UIImage * blurredImage = [UIImage imageWithCIImage:blurredCIImage];

                UIImageView *maskedImageView = [[UIImageView alloc]initWithImage:blurredImage];
                maskedImageView.contentMode = UIViewContentModeScaleAspectFit;
                maskedImageView.frame = imageview.frame;
                imageview.layer.mask=maskedImageView.layer;

                dispatch_async(dispatch_get_main_queue(), ^{
                    [self.view addSubview:imageview];
                });
            });
Reza.Ab
  • 1,195
  • 1
  • 11
  • 21
  • 1
    Where do you stop/hide the activity view? – Paulw11 Apr 30 '17 at 22:36
  • I apologize, I forgot to delete that part of the question before posting it, that's solved now. But my issue is that dispatch_Async makes my code run so much slower. Am I doing it wrong? Thank you. @Paulw11 – Reza.Ab Apr 30 '17 at 22:58

2 Answers2

3

All UI stuff should be performed on the main queue. If not, this could lead to bugs (from time to time) and incredibly slow performance.

The reason for this is because UIApplication gets set up on the main thread.

You can check this tutorial out:

  1. http://blog.grio.com/2014/04/understanding-the-ios-main-thread.html

  2. https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW15.

best regards

dmlebron
  • 861
  • 6
  • 16
  • Thank you, I only did update the UI in main queue, so there's no way that I could do the first part of my code in the background? Because I have a horizontal collectionview beneath this view which I don't want to be blocked while user scrolls and selects different effects. Shouldn't I do these stuff in the background to not block the main queue for other UI updates such as scrolling the collectionview? – Reza.Ab Apr 30 '17 at 23:08
  • 1
    You can check Facebook's library for async display kit: https://code.facebook.com/posts/721586784561674/introducing-asyncdisplaykit-for-smooth-and-responsive-apps-on-ios/ – dmlebron Apr 30 '17 at 23:26
3

GCD manages queues with different priorities. The higher the priority, the larger the percentage of the CPUs' time the jobs in that queue get.

Apple designed their priority system so that user interaction (the main thread) gets the highest priority, in order to keep the UI responsive. DISPATCH_QUEUE_PRIORITY_DEFAULT is a lower priority than the main thread, so a job submitted with that priority will take longer than one run on the main thread. You could try using DISPATCH_QUEUE_PRIORITY_HIGH as an experiment, you shouldn't do that in a production app because it will slow down the UI (and Apple may reject your app.)

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Thank you for pointing out that but I already did try DISPATCH_QUEUE_PRIORITY_HIGH and the results were just as the same as lower priorities. Really slow not much difference to using Default priority. Just asking, would you also recommend using Facebook's AsyncDisplayKit for this case too? Thanks @DuncanC – Reza.Ab Apr 30 '17 at 23:39