From b50fabe325cb77a259b47bf34e6e74e1e2ace614 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sat, 1 Feb 2020 12:19:39 -0800 Subject: [PATCH] =?UTF-8?q?Fix=20a=20crash=20that=20could=20happen=20when?= =?UTF-8?q?=20laying=20out=20the=20progress=20view=20while=20it=E2=80=99s?= =?UTF-8?q?=20not=20in=20the=20view=20hierarchy.=20Fix=20#1764.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iOS/MasterFeed/RefreshProgressView.swift | 38 ++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/iOS/MasterFeed/RefreshProgressView.swift b/iOS/MasterFeed/RefreshProgressView.swift index 09b9f6574..6a627e10a 100644 --- a/iOS/MasterFeed/RefreshProgressView.swift +++ b/iOS/MasterFeed/RefreshProgressView.swift @@ -13,7 +13,7 @@ class RefreshProgressView: UIView { @IBOutlet weak var progressView: UIProgressView! @IBOutlet weak var label: UILabel! - private lazy var progressWidth = progressView.widthAnchor.constraint(equalToConstant: 100.0) + private lazy var progressWidthConstraint = progressView.widthAnchor.constraint(equalToConstant: 100.0) override func awakeFromNib() { NotificationCenter.default.addObserver(self, selector: #selector(progressDidChange(_:)), name: .AccountRefreshProgressDidChange, object: nil) @@ -28,6 +28,10 @@ class RefreshProgressView: UIView { scheduleUpdateRefreshLabel() } + override func didMoveToSuperview() { + progressChanged() + } + func updateRefreshLabel() { if let accountLastArticleFetchEndTime = AccountManager.shared.lastArticleFetchEndTime { @@ -71,28 +75,38 @@ class RefreshProgressView: UIView { private extension RefreshProgressView { func progressChanged() { + // Layout may crash if not in the view hierarchy. + // https://github.com/Ranchero-Software/NetNewsWire/issues/1764 + let isInViewHierarchy = self.superview != nil + let progress = AccountManager.shared.combinedRefreshProgress if progress.isComplete { - progressView.setProgress(1, animated: true) + if isInViewHierarchy { + progressView.setProgress(1, animated: true) + } DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { self.updateRefreshLabel() self.label.isHidden = false self.progressView.isHidden = true - self.progressWidth.isActive = false - self.progressView.setProgress(0, animated: true) + self.progressWidthConstraint.isActive = false + if isInViewHierarchy { + self.progressView.setProgress(0, animated: true) + } } } else { label.isHidden = true progressView.isHidden = false - self.progressWidth.isActive = true - self.progressView.setNeedsLayout() - self.progressView.layoutIfNeeded() - let percent = Float(progress.numberCompleted) / Float(progress.numberOfTasks) - - // Don't let the progress bar go backwards unless we need to go back more than 25% - if percent > progressView.progress || progressView.progress - percent > 0.25 { - progressView.setProgress(percent, animated: true) + progressWidthConstraint.isActive = true + if isInViewHierarchy { + progressView.setNeedsLayout() + progressView.layoutIfNeeded() + let percent = Float(progress.numberCompleted) / Float(progress.numberOfTasks) + + // Don't let the progress bar go backwards unless we need to go back more than 25% + if percent > progressView.progress || progressView.progress - percent > 0.25 { + progressView.setProgress(percent, animated: true) + } } } }