diff --git a/Sources/ObjC/MarqueeLabel.m b/Sources/ObjC/MarqueeLabel.m index 0e6b7228..680d85b1 100755 --- a/Sources/ObjC/MarqueeLabel.m +++ b/Sources/ObjC/MarqueeLabel.m @@ -576,22 +576,38 @@ - (void)scrollAwayWithInterval:(NSTimeInterval)interval delayAmount:(NSTimeInter __weak __typeof__(self) weakSelf = self; self.scrollCompletionBlock = ^(BOOL finished) { - if (!finished || !weakSelf) { - // Do not continue into the next loop + if (!weakSelf) { return; } + // Call returned home method [weakSelf labelReturnedToHome:YES]; + // Check to ensure that: - // 1) We don't double fire if an animation already exists - // 2) The instance is still attached to a window - this completion block is called for + // 1) The instance is still attached to a window - this completion block is called for // many reasons, including if the animation is removed due to the view being removed // from the UIWindow (typically when the view controller is no longer the "top" view) - if (self.window && ![weakSelf.subLabel.layer animationForKey:@"position"]) { - // Begin again, if conditions met - if (weakSelf.labelShouldScroll && !weakSelf.tapToScroll && !weakSelf.holdScrolling) { - [weakSelf scrollAwayWithInterval:interval delayAmount:delayAmount shouldReturn:shouldReturn]; - } + if (!weakSelf.window) { + return; + } + // 2) We don't double fire if an animation already exists + if ([weakSelf.subLabel.layer animationForKey:@"position"]) { + return; + } + // 3) We don't not start automatically if the animation was unexpectedly interrupted + if (!finished) { + // Do not continue into the next loop + return; + } + // 4) A completion block still exists for the NEXT loop. A notable case here is if + // returnLabelToHome was called during a subclass's labelReturnToHome function + if (!weakSelf.scrollCompletionBlock) { + return; + } + + // Begin again, if conditions met + if (weakSelf.labelShouldScroll && !weakSelf.tapToScroll && !weakSelf.holdScrolling) { + [weakSelf scrollAwayWithInterval:interval delayAmount:delayAmount shouldReturn:shouldReturn]; } }; diff --git a/Sources/Swift/MarqueeLabel.swift b/Sources/Swift/MarqueeLabel.swift index df457755..11841d97 100644 --- a/Sources/Swift/MarqueeLabel.swift +++ b/Sources/Swift/MarqueeLabel.swift @@ -840,11 +840,6 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { #endif scrollCompletionBlock = { [weak self] (finished: Bool) -> () in - guard finished else { - // Do not continue into the next loop - return - } - guard (self != nil) else { return } @@ -853,17 +848,27 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { self!.labelReturnedToHome(true) // Check to ensure that: - // 1) We don't double fire if an animation already exists - // 2) The instance is still attached to a window - this completion block is called for + + // 1) The instance is still attached to a window - this completion block is called for // many reasons, including if the animation is removed due to the view being removed // from the UIWindow (typically when the view controller is no longer the "top" view) guard self!.window != nil else { return } - + // 2) We don't double fire if an animation already exists guard self!.sublabel.layer.animation(forKey: "position") == nil else { return } + // 3) We don't not start automatically if the animation was unexpectedly interrupted + guard finished else { + // Do not continue into the next loop + return + } + // 4) A completion block still exists for the NEXT loop. A notable case here is if + // returnLabelToHome() was called during a subclass's labelReturnToHome() function + guard (self!.scrollCompletionBlock != nil) else { + return + } // Begin again, if conditions met if (self!.labelShouldScroll() && !self!.tapToScroll && !self!.holdScrolling) {