Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getting crash in M13ProgressViewPie.m #26

Closed
rotemdoron opened this issue Mar 18, 2014 · 16 comments
Closed

getting crash in M13ProgressViewPie.m #26

rotemdoron opened this issue Mar 18, 2014 · 16 comments

Comments

@rotemdoron
Copy link

hello im not sure why but im getting this crash at :
[self.displayLink removeFromRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
not all the time but every few launches of the app

@Marxon13
Copy link
Owner

Could you use an exception breakpoint and post the crash report?

@rotemdoron
Copy link
Author

that is the crash it happens once in a while so cant realy point out what it is

@rotemdoron
Copy link
Author

screen shot 2014-03-19 at 11 29 18 am

@Marxon13
Copy link
Owner

Hmmm.... The display link is not nil... The only thing I can think of, is that the display link is invalidated, or not being run in a run loop. But as far as I can tell, there is no way to check if the runloop is invalid, or not in the main run loop. Also, apple's docs do not mention any of this will crash/error if the display link is not running.

Are you running this in the sample app, or your own app?

@rotemdoron
Copy link
Author

my own app not the sample one

@Marxon13
Copy link
Owner

Marxon13 commented Apr 7, 2014

Could you try to duplicate it with a different progress bar, perhaps the ring. I want to see if it is just the pie progress view, or if it has to do with the CADisplayLink as a whole.

@Marxon13
Copy link
Owner

Marxon13 commented Apr 7, 2014

Reading the documentation:
https://developer.apple.com/library/ios/documentation/QuartzCore/Reference/CADisplayLink_ClassRef/Reference/Reference.html
It looks like the run loop might be releasing the display link early, or the display link is releasing the target early. Try changing that line to [self.displayLink invalidate] and see if that helps/

@rotemdoron
Copy link
Author

thank you i will try that and will let u know the results!

@eltonf
Copy link

eltonf commented Apr 29, 2014

Just to add my 2 cents, I'm also seeing this issue with M13ProgressViewBorderedBar. I haven't figured out how to reproduce it though, seems to be somewhat random.

@Marxon13
Copy link
Owner

Hmmm. So I can now assume it will happen with every progress view since the CADisplayLink is used in the exact same way in every progress view.

If this happens to you again, or to anyone that reads this, can you post the error report, and tell me exactly what you were doing when it happened. I don't think anything would happen if its just "sitting" there. What I'm looking for is whether the view was animating in or out. What sort of thing is going on in the background. If there was a viewController change, etc... If we can get as much information around this bug as possible, we could figure out what is going on.

Perhaps the line removing the display link from the run loop is being called twice?

@eltonf
Copy link

eltonf commented May 1, 2014

I suspect my crashing was caused by me inadvertently updating the UI from a background thread due to a block callback. I've fixed my code to always update the progress bar from the main thread and so far I haven't seen any crashes in limited testing. I'll report back if I have any further issues when using the main thread.

@eltonf
Copy link

eltonf commented May 1, 2014

Even after moving all of my UI code to the main thread I still get the occasional crash. I believe the issue is caused by animateProgress:(CADisplayLink *)displayLink calling [self.displayLink removeFromRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes] inside of a background thread via DISPATCH_QUEUE_PRIORITY_HIGH instead of doing it on the main thread. The attached screenshot shows the crash with the concurrency issue as animateProgress is called simultaneously.

screen shot 2014-05-01 at 7 00 34 am

To add context, I have a view in my app with up to 18 M13ProgressViewBorderedBar views visible and animating simultaneously. I think this is why at seemingly random moments my app will crash, because sooner or later animateProgress: will be called twice at EXACTLY the same time.

Hence, I think the proper fix is to change:

- (void)animateProgress:(CADisplayLink *)displayLink
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        CGFloat dt = (displayLink.timestamp - _animationStartTime) / self.animationDuration;
        if (dt >= 1.0) {
            //Order is important! Otherwise concurrency will cause errors, because setProgress: will detect an animation in progress and try to stop it by itself. Once over one, set to actual progress amount. Animation is over.
            [self.displayLink removeFromRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
            self.displayLink = nil;
            dispatch_async(dispatch_get_main_queue(), ^{
                [super setProgress:_animationToValue animated:NO];
                [self setNeedsDisplay];
            });
            return;
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            //Set progress
            [super setProgress:_animationFromValue + dt * (_animationToValue - _animationFromValue) animated:YES];
            [self setNeedsDisplay];
        });

    });
}

to this:

- (void)animateProgress:(CADisplayLink *)displayLink
{
    dispatch_async(dispatch_get_main_queue(), ^{
        CGFloat dt = (displayLink.timestamp - _animationStartTime) / self.animationDuration;
        if (dt >= 1.0) {
            //Order is important! Otherwise concurrency will cause errors, because setProgress: will detect an animation in progress and try to stop it by itself. Once over one, set to actual progress amount. Animation is over.
            [self.displayLink removeFromRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
            self.displayLink = nil;
            [super setProgress:_animationToValue animated:NO];
            [self setNeedsDisplay];
            return;
        }

        //Set progress
        [super setProgress:_animationFromValue + dt * (_animationToValue - _animationFromValue) animated:YES];
        [self setNeedsDisplay];

    });
}

Marxon13 pushed a commit that referenced this issue May 17, 2014
Fix for random crashing caused by the CADisplayLink during animations.
@Marxon13
Copy link
Owner

Let me know if this fix works! Thanks @eltonf

@eltonf
Copy link

eltonf commented May 18, 2014

I never saw another crash after implementing the fix so I think it's solid.

@rotemdoron
Copy link
Author

yeap same here no crashing after this fix thanks alot @eltonf

@fengjunping
Copy link

I have the same crash and fixed by this. thanks @eltonf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants