From 1b6071675936658fa0367dbca326774936642911 Mon Sep 17 00:00:00 2001 From: Michael Kirk <michael@signal.org> Date: Thu, 17 May 2018 15:45:48 -0400 Subject: [PATCH] Stop worrying about notification order by using delegate pattern // FREEBIE --- .../ConversationViewController.m | 16 ----- .../SignalsNavigationController.m | 1 - .../ViewControllers/OWSNavigationController.m | 50 ++++++++----- SignalMessaging/Views/OWSNavigationBar.swift | 72 +++++-------------- 4 files changed, 48 insertions(+), 91 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 351223ccc..502345336 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -267,22 +267,6 @@ typedef enum : NSUInteger { return self; } -- (CGSize)sizeForChildContentContainer:(id<UIContentContainer>)container - withParentContainerSize:(CGSize)parentSize NS_AVAILABLE_IOS(8_0); -{ - CGSize result = [super sizeForChildContentContainer:container withParentContainerSize:parentSize]; - DDLogDebug(@"%@ in %s result: %@", self.logTag, __PRETTY_FUNCTION__, NSStringFromCGSize(result)); - - return result; -} - -- (void)viewWillTransitionToSize:(CGSize)size - withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator -{ - DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); - [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; -} - - (void)commonInit { _contactsManager = [Environment current].contactsManager; diff --git a/Signal/src/ViewControllers/SignalsNavigationController.m b/Signal/src/ViewControllers/SignalsNavigationController.m index 3225978e2..1ef76a540 100644 --- a/Signal/src/ViewControllers/SignalsNavigationController.m +++ b/Signal/src/ViewControllers/SignalsNavigationController.m @@ -45,7 +45,6 @@ static double const STALLED_PROGRESS = 0.9; } } - - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; diff --git a/SignalMessaging/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m index 46f29e8e0..8557d3155 100644 --- a/SignalMessaging/ViewControllers/OWSNavigationController.m +++ b/SignalMessaging/ViewControllers/OWSNavigationController.m @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface OWSNavigationController (OWSNavigationController) <UINavigationBarDelegate> +@interface OWSNavigationController (OWSNavigationController) <UINavigationBarDelegate, NavBarLayoutDelegate> @end @@ -51,42 +51,54 @@ NS_ASSUME_NONNULL_BEGIN self = [self initWithNavigationBarClass:[OWSNavigationBar class] toolbarClass:nil]; [self pushViewController:rootViewController animated:NO]; - - [self updateNavbarCallBannerLayout]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowManagerCallDidChange:) - name:OWSWindowManagerCallDidChangeNotification - object:nil]; + if (![self.navigationBar isKindOfClass:[OWSNavigationBar class]]) { + OWSFail(@"%@ navigationBar was unexpected class: %@", self.logTag, self.navigationBar); + return self; + } + + OWSNavigationBar *navbar = (OWSNavigationBar *)self.navigationBar; + navbar.navBarLayoutDelegate = self; + [self updateLayoutForNavbar:navbar]; return self; } -- (void)windowManagerCallDidChange:(NSNotification *)notification +- (void)navBarCallLayoutDidChangeWithNavbar:(OWSNavigationBar *)navbar { - DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); - [self updateNavbarCallBannerLayout]; + [self updateLayoutForNavbar:navbar]; } -- (void)updateNavbarCallBannerLayout +- (void)updateLayoutForNavbar:(OWSNavigationBar *)navbar { + DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); + if (@available(iOS 11.0, *)) { if (OWSWindowManager.sharedManager.hasCall) { self.additionalSafeAreaInsets = UIEdgeInsetsMake(64, 0, 0, 0); } else { self.additionalSafeAreaInsets = UIEdgeInsetsZero; } + [navbar layoutSubviews]; } else { - if (![self.navigationBar isKindOfClass:[OWSNavigationBar class]]) { - OWSFail(@"%@ in %s navigationBar was unexpected class", self.logTag, __PRETTY_FUNCTION__); - return; + // Pre iOS11 we have to position the frame manually + [navbar sizeToFit]; + + if (OWSWindowManager.sharedManager.hasCall) { + CGRect oldFrame = navbar.frame; + CGRect newFrame + = CGRectMake(oldFrame.origin.x, navbar.callBannerHeight, oldFrame.size.width, oldFrame.size.height); + navbar.frame = newFrame; + } else { + CGRect oldFrame = navbar.frame; + CGRect newFrame + = CGRectMake(oldFrame.origin.x, navbar.statusBarHeight, oldFrame.size.width, oldFrame.size.height); + navbar.frame = newFrame; } - OWSNavigationBar *navBar = (OWSNavigationBar *)self.navigationBar; - CGRect oldFrame = navBar.frame; - CGRect newFrame - = CGRectMake(oldFrame.origin.x, navBar.statusBarHeight, oldFrame.size.width, oldFrame.size.height); - navBar.frame = newFrame; + // Since the navbar's frame was updated, we need to be sure our child VC's + // container view is updated. + [self.view setNeedsLayout]; } } diff --git a/SignalMessaging/Views/OWSNavigationBar.swift b/SignalMessaging/Views/OWSNavigationBar.swift index 113816a31..0342968c7 100644 --- a/SignalMessaging/Views/OWSNavigationBar.swift +++ b/SignalMessaging/Views/OWSNavigationBar.swift @@ -5,9 +5,16 @@ import Foundation import UIKit +@objc +protocol NavBarLayoutDelegate: class { + func navBarCallLayoutDidChange(navbar: OWSNavigationBar) +} + @objc class OWSNavigationBar: UINavigationBar { + weak var navBarLayoutDelegate: NavBarLayoutDelegate? + // TODO - get a more precise value // TODO - test with other heights, e.g. w/ hotspot, w/ call in other app let navbarWithoutStatusHeight: CGFloat = 44 @@ -29,16 +36,8 @@ class OWSNavigationBar: UINavigationBar { @objc public func callDidChange() { - Logger.debug("\(self.logTag) in \(#function) OWSWindowManagerCallDidChange") - - if #available(iOS 11, *) { - self.layoutSubviews() - } else { - self.sizeToFit() - self.frame.origin.y = statusBarHeight - - self.layoutSubviews() - } + Logger.debug("\(self.logTag) in \(#function)") + self.navBarLayoutDelegate?.navBarCallLayoutDidChange(navbar: self) } required init?(coder aDecoder: NSCoder) { @@ -53,9 +52,9 @@ class OWSNavigationBar: UINavigationBar { if #available(iOS 11, *) { return super.sizeThatFits(size) } else { - // pre iOS11, sizeThatFits is repeatedly called to size the navbar - // as of iOS11, this is not true and we have to size things in layoutSubviews. - // FIXME: pre-iOS11, though the size is right, there's a glitch on the titleView while push/popping items. + // pre iOS11, sizeThatFits is repeatedly called to determine how much space to reserve for that navbar. + // That is, increasing this causes the child view controller to be pushed down. + // (as of iOS11, this is not used and instead we use additionalSafeAreaInsets) let result = CGSize(width: CurrentAppContext().mainWindow!.bounds.width, height: navbarWithoutStatusHeight + statusBarHeight) Logger.debug("\(self.logTag) in \(#function): \(result)") @@ -64,52 +63,10 @@ class OWSNavigationBar: UINavigationBar { } } -// override var center: CGPoint { -// get { -// Logger.debug("\(self.logTag) in \(#function)") -// return super.center -// } -// set { -// Logger.debug("\(self.logTag) in \(#function)") -// if OWSWindowManager.shared().hasCall() { -// var translated = newValue -//// translated.y -= 20 -// super.center = translated -// } else { -// super.center = newValue -// } -// } -// } - - // seems unused. -// override var intrinsicContentSize: CGSize { -// return CGSize(width: UIScreen.main.bounds.width, height: navbarWithoutStatusHeight) -// return CGSize(width: UIScreen.main.bounds.width, height: 20) -// } - -// override var bounds: CGRect { -// get { -// return super.bounds -// } -// set { -// super.bounds = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: ios11NavbarHeight) -// } -// } -// -// override var frame: CGRect { -// get { -// return super.frame -// } -// set { -// super.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: ios11NavbarHeight) -// } -// } - override func layoutSubviews() { Logger.debug("\(self.logTag) in \(#function)") guard OWSWindowManager.shared().hasCall() else { -// guard #available(iOS 11.0, *), OWSWindowManager.shared().hasCall() else { super.layoutSubviews() return } @@ -121,6 +78,11 @@ class OWSNavigationBar: UINavigationBar { super.layoutSubviews() + guard #available(iOS 11, *) else { + return + } + + // This is only necessary on iOS11, which has some private views within the navbar for subview in self.subviews { let stringFromClass = NSStringFromClass(subview.classForCoder) if stringFromClass.contains("BarBackground") {